action_args 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e820e5d9674aa0054496752320674fc8c57c364d
4
+ data.tar.gz: c854a76604f95d555872c93cc360ad42d19425e8
5
+ SHA512:
6
+ metadata.gz: b82fea159869a228853c9362d9b321c9a4ef3e9f88b20be10a74b16c96c494317a96fa99936ff7ae2261812645cf89c6e68f959ee802eb942310c35df6126ccf
7
+ data.tar.gz: 85e3e9513651c34edce33142cc2fa4dc0d539f1eb9163a0464bcdb82686ebac6e549b2963406b56605f3376519b1d3847b576d2f14949749704ef80d4351960e
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in action_args.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -158,7 +158,7 @@ You may notice that
158
158
 
159
159
  ## Supported versions
160
160
 
161
- * Ruby 1.9.2, 1.9.3, 2.0.0 (trunk), JRuby & Rubinius with 1.9 mode
161
+ * Ruby 1.9.2, 1.9.3, 2.0.0, 2.1.0 (trunk), JRuby & Rubinius with 1.9 mode
162
162
 
163
163
  * Rails 3.0.x, 3.1.x, 3.2.x, 4.0 (edge)
164
164
 
@@ -201,6 +201,31 @@ class BooksController < ApplicationController
201
201
  end
202
202
  ```
203
203
 
204
+ ### Default parameter values
205
+
206
+ You are of course able to specify default values for action parameters such as:
207
+
208
+ ```ruby
209
+ class BooksController < ApplicationController
210
+ def index(author_id = nil, page = 1)
211
+ ...
212
+ end
213
+ end
214
+ ```
215
+
216
+ However, due to some implementational reasons, the `page` variable will be actually defaulted to nil when `page` parameter was not given.
217
+
218
+ In order to provide default parameter values in perfect Ruby manner, we recommend you to use the Ruby 2.0 "keyword arguments" syntax instead.
219
+
220
+ ```ruby
221
+ class BooksController < ApplicationController
222
+ def index(author_id: nil, page: 1)
223
+ ...
224
+ end
225
+ end
226
+ ```
227
+
228
+ This way, the `page` parameter will be defaulted to 1 as everyone might expect.
204
229
 
205
230
  ## Copyright
206
231
 
data/Rakefile CHANGED
@@ -19,7 +19,7 @@ namespace :spec do
19
19
  end
20
20
  end
21
21
 
22
- desc 'Run Tests against all ORMs'
22
+ desc 'Run Tests against all Rails versions'
23
23
  task :all do
24
24
  %w(rails_32 rails_40).each do |gemfile|
25
25
  sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '>= 3.2.9'
4
4
  gem 'rspec-rails', '>= 2.0'
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', github: 'rails/rails'
4
4
  gem 'activerecord-deprecated_finders', github: 'rails/activerecord-deprecated_finders'
data/lib/action_args.rb CHANGED
@@ -2,6 +2,7 @@ begin
2
2
  require 'strong_parameters'
3
3
  rescue LoadError
4
4
  end
5
+ require 'action_args/params_handler'
5
6
  require 'action_args/abstract_controller'
6
7
 
7
8
  module ActionArgs
@@ -4,16 +4,9 @@ module AbstractController
4
4
  def send_action(method_name, *args)
5
5
  return send method_name, *args unless args.empty?
6
6
 
7
- target_model_name = self.class.name.sub(/Controller$/, '').singularize.underscore.to_sym
8
- permitted_attributes = self.class.instance_variable_get '@permitted_attributes'
9
- values = method(method_name).parameters.reject {|type, _| type == :block }.map do |type, key|
10
- params.require key if type == :req
11
- if (key == target_model_name) && permitted_attributes
12
- params[key].try :permit, *permitted_attributes
13
- else
14
- params[key]
15
- end
16
- end
7
+ method_parameters = method(method_name).parameters
8
+ ActionArgs::ParamsHandler.strengthen_params!(self.class, method_parameters, params)
9
+ values = ActionArgs::ParamsHandler.extract_method_arguments_from_params method_parameters, params
17
10
  send method_name, *values
18
11
  end
19
12
 
@@ -37,7 +30,7 @@ module AbstractController
37
30
  def send_action(method_name, *args)
38
31
  return send method_name, *args unless args.empty?
39
32
 
40
- values = method(method_name).parameters.reject {|type, _| type == :block }.map {|_, key| params[key]}
33
+ values = ActionArgs::ParamsHandler.extract_method_arguments_from_params method(method_name).parameters, params
41
34
  send method_name, *values
42
35
  end
43
36
  end
@@ -0,0 +1,38 @@
1
+ module ActionArgs
2
+ module ParamsHandler
3
+ # converts the request params Hash into an Array to be passed into the target Method
4
+ def self.extract_method_arguments_from_params(method_parameters, params)
5
+ kwargs = {}
6
+ parameter_names = method_parameters.map(&:last)
7
+ method_parameters.reverse_each do |type, key|
8
+ case type
9
+ when :req
10
+ next
11
+ when :key
12
+ kwargs[key] = params[key] if params.has_key? key
13
+ when :opt
14
+ break if params.has_key? key
15
+ end
16
+ # omitting parameters that are :block, :rest, :opt without a param, and :key without a param
17
+ parameter_names.delete key
18
+ end
19
+
20
+ values = parameter_names.map {|k| params[k]}
21
+ values << kwargs if kwargs.any?
22
+ values
23
+ end
24
+
25
+ # permits declared model attributes in the params Hash
26
+ # note that this method mutates the given params Hash
27
+ def self.strengthen_params!(controller_class, method_parameters, params)
28
+ target_model_name = controller_class.name.sub(/.+::/, '').sub(/Controller$/, '').singularize.underscore.to_sym
29
+ permitted_attributes = controller_class.instance_variable_get '@permitted_attributes'
30
+
31
+ method_parameters.each do |type, key|
32
+ if (key == target_model_name) && permitted_attributes
33
+ params[key] = params.require(key).try :permit, *permitted_attributes
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module ActionArgs
2
- VERSION = '1.0.4'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -2,14 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  describe BooksController do
4
4
  describe 'GET index (having an optional parameter)' do
5
+ before do
6
+ @books = []
7
+ Book.delete_all
8
+ 100.times {|i| @books << Book.create!(title: 'book'+i.to_s) }
9
+ end
5
10
  context 'without page parameter' do
6
11
  before { get :index }
7
12
  its(:response) { should be_success }
13
+ it { expect(assigns(:books)).to match_array(@books[0..9]) }
8
14
  end
9
15
 
10
16
  context 'with page parameter' do
11
17
  before { get :index, page: 3 }
12
18
  its(:response) { should be_success }
19
+ it { expect(assigns(:books)).to match_array(@books[20..29]) }
13
20
  end
14
21
 
15
22
  context 'first param is nil and second is not nil' do
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe KwBooksController do
4
+ describe 'GET index (having an optional parameter)' do
5
+ context 'without giving any kw parameter' do
6
+ before { get :index, author_name: 'nari' }
7
+ its(:response) { should be_success }
8
+ end
9
+
10
+ context 'with kw parameter defaults to non-nil value' do
11
+ before { get :index, author_name: 'nari', page: 3 }
12
+ subject { eval response.body }
13
+ its([:author_name]) { should == 'nari' }
14
+ its([:page]) { should == '3' }
15
+ its([:q]) { should == nil }
16
+ end
17
+
18
+ context 'with kw parameter defaults to nil' do
19
+ before { get :index, author_name: 'nari', q: 'Rails' }
20
+ subject { eval response.body }
21
+ its([:author_name]) { should == 'nari' }
22
+ its([:page]) { should == '1' }
23
+ its([:q]) { should == 'Rails' }
24
+ end
25
+ end
26
+ end if RUBY_VERSION >= '2'
@@ -13,4 +13,16 @@ if Rails::VERSION::MAJOR >= 4
13
13
  it { expect { post :create, :store => {name: 'Tatsu-zine', url: 'http://tatsu-zine.com'} }.to change(Store, :count).by(1) }
14
14
  end
15
15
  end
16
+
17
+ describe Admin::BooksController do
18
+ context "this controller doesn't permit price of new book" do
19
+ describe 'POST create' do
20
+ before { post :create, :book => {title: 'naruhoUnix', price: 30} }
21
+
22
+ it 'should not save price of the book' do
23
+ expect(Book.last.price).to be_nil
24
+ end
25
+ end
26
+ end
27
+ end
16
28
  end
data/spec/fake_app.rb CHANGED
@@ -15,7 +15,12 @@ ActionArgsTestApp::Application.initialize!
15
15
  ActionArgsTestApp::Application.routes.draw do
16
16
  resources :authors
17
17
  resources :books
18
+ resources :kw_books # 2.0+ only
18
19
  resources :stores
20
+
21
+ namespace :admin do
22
+ resources :books
23
+ end
19
24
  end
20
25
 
21
26
  # models
@@ -40,10 +45,10 @@ class AuthorsController < ApplicationController
40
45
  end
41
46
  class BooksController < ApplicationController
42
47
  # optional parameter
43
- def index(page = 1, q = nil)
44
- @books = Book.limit(10).offset(([page.to_i - 1, 0].max) * 10)
48
+ def index(page = 1, q = nil, limit = 10)
49
+ @books = Book.limit(limit.to_i).offset(([page.to_i - 1, 0].max) * 10)
45
50
  @books = @books.where('title like ?', "%#{q}%") unless q.blank?
46
- render text: 'index'
51
+ render text: 'index', books: @books
47
52
  end
48
53
 
49
54
  def show(id)
@@ -71,8 +76,20 @@ if Rails::VERSION::MAJOR >= 4
71
76
  render text: @store.name
72
77
  end
73
78
  end
79
+ module Admin
80
+ class BooksController < ::ApplicationController
81
+ permits :title
82
+
83
+ def create(book)
84
+ @book = Book.create! book
85
+ render text: @book.title
86
+ end
87
+ end
88
+ end
74
89
  end
75
90
 
91
+ require_relative 'kwargs_controllers' if RUBY_VERSION >= '2'
92
+
76
93
  # migrations
77
94
  class CreateAllTables < ActiveRecord::Migration
78
95
  def self.up
@@ -0,0 +1,8 @@
1
+ # this file should not be loaded from Ruby <2.0
2
+
3
+ class KwBooksController < ApplicationController
4
+ # keyword arguments
5
+ def index(author_name, page: '1', q: nil)
6
+ render text: {author_name: author_name, page: page, q: q}.inspect
7
+ end
8
+ end
@@ -0,0 +1,158 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActionArgs::ParamsHandler do
4
+ # ActionArgs::ParamsHandler.extract_method_arguments_from_params(method_parameters, params)
5
+ describe 'extract_method_arguments_from_params' do
6
+ let(:params) { {a: '1', b: '2'} }
7
+ subject { ActionArgs::ParamsHandler.extract_method_arguments_from_params method(:m).parameters, params }
8
+ context 'no parameters' do
9
+ before do
10
+ def m() end
11
+ end
12
+ it { should == [] }
13
+ end
14
+
15
+ context '1 req' do
16
+ before do
17
+ def m(a) end
18
+ end
19
+ it { should == ['1'] }
20
+ end
21
+
22
+ context '2 reqs' do
23
+ before do
24
+ def m(a, b) end
25
+ end
26
+ it { should == ['1', '2'] }
27
+ end
28
+
29
+ context '1 opt with value' do
30
+ before do
31
+ def m(a = 'a') end
32
+ end
33
+ it { should == ['1'] }
34
+ end
35
+
36
+ context '1 opt without value' do
37
+ before do
38
+ def m(x = 'x') end
39
+ end
40
+ it { should == [] }
41
+ end
42
+
43
+ context 'req, opt with value' do
44
+ before do
45
+ def m(a, b = 'b') end
46
+ end
47
+ it { should == ['1', '2'] }
48
+ end
49
+
50
+ context 'req, opt without value' do
51
+ before do
52
+ def m(a, x = 'x') end
53
+ end
54
+ it { should == ['1'] }
55
+ end
56
+
57
+ context 'opt with value, opt with value' do
58
+ before do
59
+ def m(a = 'a', b = 'b') end
60
+ end
61
+ it { should == ['1', '2'] }
62
+ end
63
+
64
+ context 'opt with value, opt without value' do
65
+ before do
66
+ def m(a = 'a', x = 'x') end
67
+ end
68
+ it { should == ['1'] }
69
+ end
70
+
71
+ context 'opt without value, opt with value' do
72
+ before do
73
+ def m(x = 'x', a = 'a') end
74
+ end
75
+ it { should == [nil, '1'] }
76
+ end
77
+
78
+ context 'opt without value, opt without value' do
79
+ before do
80
+ def m(x = 'x', y = 'y') end
81
+ end
82
+ it { should == [] }
83
+ end
84
+
85
+ context 'opt with value, req' do
86
+ before do
87
+ def m(a = 'a', b) end
88
+ end
89
+ it { should == ['1', '2'] }
90
+ end
91
+
92
+ context 'opt without value, req' do
93
+ before do
94
+ def m(x = 'x', a) end
95
+ end
96
+ it { should == ['1'] }
97
+ end
98
+
99
+ context 'opt without value, opt with value, req' do
100
+ before do
101
+ def m(x = 'x', b = 'b', a) end
102
+ end
103
+ it { should == [nil, '2', '1'] }
104
+ end
105
+ context 'opt with value, opt without value, req' do
106
+ before do
107
+ def m(b = 'b', x = 'x', a) end
108
+ end
109
+ it { should == ['2', '1'] }
110
+ end
111
+ end
112
+
113
+ if defined? ActionController::StrongParameters
114
+ # strengthen_params!(controller_class, method_parameters, params)
115
+ describe 'strengthen_params!' do
116
+ before { ActionArgs::ParamsHandler.strengthen_params! controller, controller.new.method(:a).parameters, params }
117
+ let(:params) { ActionController::Parameters.new(x: '1', y: '2', foo: {a: 'a', b: 'b'}, bar: {a: 'a', b: 'b'}, baz: {a: 'a', b: 'b'}, hoge: {a: 'a', b: 'b'}, fuga: {a: 'a', b: 'b'}) }
118
+
119
+ context 'requiring via :req, permitting all scalars' do
120
+ let(:controller) { FooController ||= Class.new(ApplicationController) { permits :a, :b; def a(foo) end } }
121
+ subject { params[:foo] }
122
+ it { should be_permitted }
123
+ its([:a]) { should be }
124
+ its([:b]) { should be }
125
+ end
126
+
127
+ context 'requiring via :req, not permitting all scalars' do
128
+ let(:controller) { BarController ||= Class.new(ApplicationController) { permits :a; def a(bar, x = 'x') end } }
129
+ subject { params[:bar] }
130
+ it { should be_permitted }
131
+ its([:a]) { should be }
132
+ its([:b]) { should_not be }
133
+ end
134
+
135
+ context 'requiring via :req, not permitting any scalars' do
136
+ let(:controller) { BazController ||= Class.new(ApplicationController) { def a(baz, aho = 'omg') end } }
137
+ subject { params[:baz] }
138
+ it { should_not be_permitted }
139
+ end
140
+
141
+ context 'requiring via :opt, permitting all scalars' do
142
+ let(:controller) { HogeController ||= Class.new(ApplicationController) { permits :a, :b; def a(hoge = {}) end } }
143
+ subject { params[:hoge] }
144
+ it { should be_permitted }
145
+ its([:a]) { should be }
146
+ its([:b]) { should be }
147
+ end
148
+
149
+ context 'requiring via :key, permitting all scalars' do
150
+ let(:controller) { FugaController ||= Class.new(ApplicationController) { permits :a, :b; def a(fuga: {}) end } }
151
+ subject { params[:fuga] }
152
+ it { should be_permitted }
153
+ its([:a]) { should be }
154
+ its([:b]) { should be }
155
+ end
156
+ end
157
+ end
158
+ end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_args
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Akira Matsuda
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-12-12 00:00:00.000000000 Z
11
+ date: 2013-05-21 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: Rails plugin gem that supports Merbish style controller action arguments.
15
14
  email:
@@ -29,43 +28,49 @@ files:
29
28
  - gemfiles/rails_40.gemfile
30
29
  - lib/action_args.rb
31
30
  - lib/action_args/abstract_controller.rb
31
+ - lib/action_args/params_handler.rb
32
32
  - lib/action_args/version.rb
33
33
  - lib/generators/action_args/rspec/scaffold/scaffold_generator.rb
34
34
  - lib/generators/action_args/rspec/scaffold/templates/action_args_controller_spec.rb
35
35
  - lib/generators/rails/action_args_scaffold_controller_generator.rb
36
36
  - lib/generators/rails/templates/controller.rb
37
37
  - spec/controllers/action_args_controller_spec.rb
38
+ - spec/controllers/kwargs_controller_spec.rb
38
39
  - spec/controllers/ordinal_controller_spec.rb
39
40
  - spec/controllers/strong_parameters_spec.rb
40
41
  - spec/fake_app.rb
42
+ - spec/kwargs_controllers.rb
43
+ - spec/params_handler/params_handler_spec.rb
41
44
  - spec/spec_helper.rb
42
45
  homepage: http://asakusa.rubyist.net/
43
46
  licenses: []
47
+ metadata: {}
44
48
  post_install_message:
45
49
  rdoc_options: []
46
50
  require_paths:
47
51
  - lib
48
52
  required_ruby_version: !ruby/object:Gem::Requirement
49
- none: false
50
53
  requirements:
51
- - - ! '>='
54
+ - - '>='
52
55
  - !ruby/object:Gem::Version
53
56
  version: '0'
54
57
  required_rubygems_version: !ruby/object:Gem::Requirement
55
- none: false
56
58
  requirements:
57
- - - ! '>='
59
+ - - '>='
58
60
  - !ruby/object:Gem::Version
59
61
  version: '0'
60
62
  requirements: []
61
63
  rubyforge_project: action_args
62
- rubygems_version: 1.8.24
64
+ rubygems_version: 2.0.2
63
65
  signing_key:
64
- specification_version: 3
66
+ specification_version: 4
65
67
  summary: Controller action arguments parameterizer for Rails 3+ & Ruby 1.9+
66
68
  test_files:
67
69
  - spec/controllers/action_args_controller_spec.rb
70
+ - spec/controllers/kwargs_controller_spec.rb
68
71
  - spec/controllers/ordinal_controller_spec.rb
69
72
  - spec/controllers/strong_parameters_spec.rb
70
73
  - spec/fake_app.rb
74
+ - spec/kwargs_controllers.rb
75
+ - spec/params_handler/params_handler_spec.rb
71
76
  - spec/spec_helper.rb