Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibility to define reusable params. #550

Merged
merged 1 commit into from
Jan 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Next Release
* [#540](https://github.com/intridea/grape/pull/540): Ruby 2.1.0 is now supported - [@salimane](https://github.com/salimane).
* [#544](https://github.com/intridea/grape/pull/544): The `rescue_from` keyword now handles subclasses of exceptions by default - [@xevix](https://github.com/xevix).
* [#545](https://github.com/intridea/grape/pull/545): Added `type` (Array or Hash) support to `requires`, `optional` and `group` - [@bwalex](https://github.com/bwalex).
* [#550](https://github.com/intridea/grape/pull/550): Added possibility to define reusable params - [@dm1try](https://github.com/dm1try).
* Your contribution here.

#### Fixes
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,58 @@ class API < Grape::API
end
```

You can define reusable `params` using `helpers`.

```ruby
class API < Grape::API
helpers do
params :pagination do
optional :page, type: Integer
optional :per_page, type: Integer
end
end

desc "Get collection"
params do
use :pagination # aliases: includes, use_scope
end
get do
Collection.page(params[:page]).per(params[:per_page])
end
end
```

You can also define reusable `params` using shared helpers.

```ruby
module SharedParams
extend Grape::API::Helpers

params :period do
optional :start_date
optional :end_date
end

params :pagination do
optional :page, type: Integer
optional :per_page, type: Integer
end
end

class API < Grape::API
helpers SharedParams

desc "Get collection"
params do
use :period, :pagination
end
get do
Collection.from(params[:start_date]).to(params[:end_date])
.page(params[:page]).per(params[:per_page])
end
end
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this should be written in two parts. One that is very simple and clear: you can define reusable params in helpers. And then a separate part that says that you can define shared helpers. It seems otherwise a little too complicated for a novice?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I agree.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange things, why these notes are here?) It's updated file.


## Cookies

You can set, get and delete your cookies very simply using `cookies` method.
Expand Down
36 changes: 35 additions & 1 deletion lib/grape/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,16 @@ def helpers(new_mod = nil, &block)
if block_given? || new_mod
mod = settings.peek[:helpers] || Module.new
if new_mod
inject_api_helpers_to_mod(new_mod) if new_mod.is_a?(Helpers)
mod.class_eval do
include new_mod
end
end
mod.class_eval(&block) if block_given?
if block_given?
inject_api_helpers_to_mod(mod) do
mod.class_eval(&block)
end
end
set(:helpers, mod)
else
mod = Module.new
Expand Down Expand Up @@ -509,6 +514,12 @@ def inherit_settings(other_stack)
e.options[:app].inherit_settings(other_stack) if e.options[:app].respond_to?(:inherit_settings, true)
end
end

def inject_api_helpers_to_mod(mod, &block)
mod.extend(Helpers)
yield if block_given?
mod.api_changed(self)
end
end

def initialize
Expand Down Expand Up @@ -581,5 +592,28 @@ def add_head_not_allowed_methods_and_options_methods
end
end
end

# This module extends user defined helpers
# to provide some API-specific functionality
module Helpers
attr_accessor :api
def params(name, &block)
@named_params ||= {}
@named_params.merge! name => block
end

def api_changed(new_api)
@api = new_api
process_named_params
end

protected

def process_named_params
if @named_params && @named_params.any?
api.imbue(:named_params, @named_params)
end
end
end
end
end
12 changes: 12 additions & 0 deletions lib/grape/validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ def params(params)
params
end

def use(*names)
named_params = @api.settings[:named_params] || {}
names.each do |name|
params_block = named_params.fetch(name) do
raise "Params :#{name} not found!"
end
instance_eval(&params_block)
end
end
alias_method :use_scope, :use
alias_method :includes, :use

def full_name(name)
return "#{@parent.full_name(@element)}[#{name}]" if @parent
name.to_s
Expand Down
55 changes: 55 additions & 0 deletions spec/grape/validations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -698,5 +698,60 @@ def validate_param!(attr_name, params)
end
end
end # end custom validation

context 'named' do
context 'can be defined' do
it 'in helpers' do
subject.helpers do
params :pagination do
end
end
end

it 'in helper module which kind of Grape::API::Helpers' do
module SharedParams
extend Grape::API::Helpers
params :pagination do
end
end
subject.helpers SharedParams
end
end

context 'can be included in usual params' do
before do
module SharedParams
extend Grape::API::Helpers
params :period do
optional :start_date
optional :end_date
end
end
subject.helpers SharedParams

subject.helpers do
params :pagination do
optional :page, type: Integer
optional :per_page, type: Integer
end
end
end

it 'by #use' do
subject.params do
use :pagination
end
subject.settings[:declared_params].should eq [:page, :per_page]
end

it 'by #use with multiple params' do
subject.params do
use :pagination, :period
end
subject.settings[:declared_params].should eq [:page, :per_page, :start_date, :end_date]
end

end
end
end
end