Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Integration with strong_parameters #236

Closed
dpmccabe opened this Issue · 14 comments

9 participants

@dpmccabe

Has anyone figured out a way to integrate Inherited Resources with the Strong Parameters gem, which might be making its way into Rails 4? Sure, you could overwrite the create and update actions on all of your controllers, but that would defeat the purpose of using Inherited Resources at all.

@khelben

You need to overwrite the #resource_params method in your controller.

One gotcha though, you'll need to wrap the result in an array like this:
Second gotcha, IR also calls this method on get #new where the params most off the time is empty and would raise an ParamsRequiredError.

def resource_params
    return [] if request.get?
    [ params.require(:employee).permit(:name, :age) ]
end

edit: update example, thx to @btucker
edit2: thx @anlek for reminding me of the get #new issue

@btucker

@khelben I believe the method name in your example above should be resource_params.

@khelben

@btucker thx for spotting, updated the example

@anlek

This seems to raise a Required parameter missing: page on the new action when I have this set:

  def resource_params
    [ params.require(:page).permit(:title, :permalink, :content) ]
  end
@khelben

That means that your params hash is missing the required ':page' key.

@anlek

Understood, but the 'new' action doesn't require the params hash at all. (unless it fail validation)

@khelben

You're right. You've hit something I've encountered myself.

The thing is: inherited resources also calls #resource_params on a new action, where most of the times the params is empty.

I've updated the example with some more explanation

@xxswingxx

Hi, I've been trying to use inherited resources with the strong_parameters gem as seen here.
It almost works, the only problem is that when the parameters reach the sanitize_for_mass_assignmentmethod from ActiveModel::ForbiddenAttributesProtection it is converted from ActionController::Parameters to Hash, so the method ignores it because it doesn't respond to the method permit. This causes that it allows mass assignment for unpermitted attributes if they are passed as a Hash instead an ActionController::Parameters. Is anyone having the same issue?

EDIT: Nevermind, it was a problem with mongoid and how it passes multiparameter attributes to the method. I've already fixed it.

@aaronchi

Hey guys,

This is actually really easy. Not sure why everyone is having so much trouble with it. Just drop this into an intitializer

inherited_resources_strong_parameters.rb

# Add Strong Attributes suuport to all models (Remove in Rails4)
ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection)

# MonkeyPatch Inherited Resources to support strong parameters
module InheritedResources
  module BaseHelpers
    protected

      def build_resource
        get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, request.get ? {} : resource_params))
      end

      def update_resource(object, attributes)
        object.update_attributes(attributes)
      end

  end
end

Now just define your params as you would for strong_attributes using resource_params

def resource_params
  params.require(:group).permit(:name, :description)
end

The main issue is that inherited_resources was splatting the attirbutes to support stuff like {params}, {:role => 'admin'}
Since roles have been removed in Rails4, we just need to remove the splat from the build and update methods and it works fine. We also skip the params for get requests since build_resource runs for new as well.

@joelmoss

Even better, please fork and submit a pull request with these changes (along with tests) and we can release it as part of the next IR release.

@joelmoss joelmoss closed this
@aaronchi

Sure. Just wanted to provide and interim solution for those who were asking. I can make a pull request with tests for Rails 4 as long as it doesn't need to be backwards compatible.

@joelmoss
@emilford

@aaronchi,

I was getting the error "undefined method get" and had to change request.get to request.get? in the build_resource method.

I am also still working on getting the permitted parameters working. Currently updates aren't being made on the resource, despite the attribute being in the list. This works. The problem was in my code.

@taavo

Note that @aaronchi's patch above only works if you're using params.require. This patch may be more versatile:

module InheritedResources
  module BaseHelpers
    protected
      def resource_params
        parameters = respond_to?(:permitted_params) ? permitted_params : params
        rparams = [parameters[resource_request_name] || parameters[resource_instance_name] || {}]
        rparams << as_role if role_given?
        rparams
      end
  end
end

Then set what parameters are permitted in the controller, in a method named permitted_params:

def permitted_params
  params.permit(:other_parameter, :group => [:name, :description])
end

(It seems like a strong_parameters api problem that permit stays at the top of the params hash, but require drills down a level, leaving no way to require one parameter but not the other. Maybe they'll sort that out eventually.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.