Skip to content

Commit

Permalink
strong parameters support refined
Browse files Browse the repository at this point in the history
  • Loading branch information
VorontsovIE committed Apr 4, 2014
1 parent 5b61f8a commit d1ad934
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Gemfile
Expand Up @@ -5,3 +5,7 @@ gemspec
gem 'rails', '>= 3.2', '< 5'
gem 'mocha'
gem 'turn'

group :test do
gem 'strong_parameters'
end
5 changes: 5 additions & 0 deletions Gemfile.lock
Expand Up @@ -80,6 +80,10 @@ GEM
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (~> 2.8)
strong_parameters (0.1.4)
actionpack (>= 3.2.0)
activemodel (>= 3.2.0)
railties (>= 3.2.0)
thor (0.18.1)
thread_safe (0.1.2)
atomic
Expand All @@ -98,4 +102,5 @@ DEPENDENCIES
inherited_resources!
mocha
rails (>= 3.2, < 5)
strong_parameters
turn
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -706,6 +706,16 @@ def build_resource_params
end
```


Instead you can stick to a standard Rails 4 notation (as rails scaffold generates) and write:

def widget_params
params.require(:widget).permit(:permitted_field, :other_permitted_field)
end

In such case you should remove #permitted_params method because it has greater priority.


## Bugs and Feedback

If you discover any bugs, please describe it in the issues tracker, including Rails and InheritedResources versions.
Expand Down
37 changes: 36 additions & 1 deletion lib/inherited_resources/base_helpers.rb
Expand Up @@ -316,9 +316,44 @@ def resource_params
@resource_params ||= build_resource_params
end

def resource_params_method_name
"#{resource_instance_name}_params"
end

# Returns hash of sanitized params in a form like
# `{:project => {:project_attribute => 'value'}}`
#
# This method makes use of `project_params` (or `smth_else_params`) which
# is a default Rails controller method for strong parameters definition.
#
# `permitted_params` is usually fired by method :new, :create, :update
# actions. Action :new usually has no parameters so strong parameters
# `require` directive raises a +ActionController::ParameterMissing+
# exception. `#permitted_params` rescues such exceptions in :new and
# returns an empty hash of parameters (which is reasonable default).
# If for any reasons you need something more specific, you can redefine
# this method in a way previous `inherited_resources` versions did:
#
# # Unnecessary redefinition
# def permitted_params
# params.permit(:project => [:project_attribute])
# end
#
def permitted_params
return nil unless respond_to?(resource_params_method_name, true)
{resource_request_name => send(resource_params_method_name)}
rescue ActionController::ParameterMissing
# typically :new action
if params[:action].to_s == 'new'
{resource_request_name => {}}
else
raise
end
end

# extract attributes from params
def build_resource_params
parameters = respond_to?(:permitted_params, true) ? permitted_params : params
parameters = permitted_params || params
rparams = [parameters[resource_request_name] || parameters[resource_instance_name] || {}]
if without_protection_given?
rparams << without_protection
Expand Down
85 changes: 84 additions & 1 deletion test/strong_parameters_test.rb
@@ -1,12 +1,17 @@
require File.expand_path('test_helper', File.dirname(__FILE__))

if ActionPack::VERSION::MAJOR == 3
require 'strong_parameters'
end

class Widget
extend ActiveModel::Naming
end

class WidgetsController < InheritedResources::Base
end

# test usage of `permitted_params`
class StrongParametersTest < ActionController::TestCase
def setup
@controller = WidgetsController.new
Expand Down Expand Up @@ -34,4 +39,82 @@ def test_permitted_params_from_update
Widget.expects(:find).with('42').returns(mock_widget)
put :update, :id => '42', :widget => {:permitted => 'param', :prohibited => 'param'}
end
end

# `permitted_params` has greater priority than `widget_params`
def test_with_permitted_and_resource_methods
@controller.stubs(:widget_params).returns(:permitted => 'another_param')
class << @controller
private :widget_params
end
Widget.expects(:new).with(:permitted => 'param')
get :new, :widget => { :permitted => 'param', :prohibited => 'param' }
end
end

# test usage of `widget_params`
class StrongParametersWithoutPermittedParamsTest < ActionController::TestCase
def setup
@controller = WidgetsController.new
@controller.stubs(:widget_url).returns("/")
@controller.stubs(:widget_params).returns(:permitted => 'param')
class << @controller
private :widget_params
end
end

def test_permitted_params_from_new
Widget.expects(:new).with(:permitted => 'param')
get :new, :widget => { :permitted => 'param', :prohibited => 'param' }
end

def test_permitted_params_from_create
Widget.expects(:new).with(:permitted => 'param').returns(mock(:save => true))
post :create, :widget => { :permitted => 'param', :prohibited => 'param' }
end

def test_permitted_params_from_update
mock_widget = mock
mock_widget.stubs(:class).returns(Widget)
mock_widget.expects(:update_attributes).with(:permitted => 'param')
Widget.expects(:find).with('42').returns(mock_widget)
put :update, :id => '42', :widget => {:permitted => 'param', :prohibited => 'param'}
end
end

# test usage of `widget_params` integrated with strong parameters (not using stubs)
class StrongParametersIntegrationTest < ActionController::TestCase
def setup
@controller = WidgetsController.new
@controller.stubs(:widget_url).returns("/")

class << @controller
define_method :widget_params do
params.require(:widget).permit(:permitted)
end
private :widget_params
end
end

def test_permitted_empty_params_from_new
Widget.expects(:new).with({})
get :new, {}
end

def test_permitted_params_from_new
Widget.expects(:new).with('permitted' => 'param')
get :new, :widget => { :permitted => 'param', :prohibited => 'param' }
end

def test_permitted_params_from_create
Widget.expects(:new).with('permitted' => 'param').returns(mock(:save => true))
post :create, :widget => { :permitted => 'param', :prohibited => 'param' }
end

def test_permitted_params_from_update
mock_widget = mock
mock_widget.stubs(:class).returns(Widget)
mock_widget.expects(:update_attributes).with('permitted' => 'param')
Widget.expects(:find).with('42').returns(mock_widget)
put :update, :id => '42', :widget => {:permitted => 'param', :prohibited => 'param'}
end
end

0 comments on commit d1ad934

Please sign in to comment.