action_args 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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