1
votes

Based on a users authorization, I'd like to sanitize the parameters to include the ones which they are allowed to update. There are 5 different roles for the one model, and I'd rather not list out 25 possible combinations and call

params.require(:asset).permit( stuff )

25 times

Is there a way to "build" the strong parameters? The only possible way I've found is "merge" but I can't seem to get it to work

This is where I'm at:

def update_params
    p = params.require(:asset)
    if can? :update, Asset
      p.merge params.require(:asset).permit(:code, :description)
    end
    if can? :update, Ability::THING1
      p.merge params.require(:asset).permit(:some_nested_stuff => [:id, :quantity, :_destroy],
                   :some_other_nested_stuff => [:id, :quantity, :_destroy])
    end
    if can? :update, Ability::THING2
      p.merge params.require(:asset).permit(more_nested_stuff: [:id, :date, :note])
    end
    if can? :update, AssetNote
      p.merge params.require(:asset).permit(notes_attributes: [:id, :note, :_destroy])
    end
    p
  end

With this I get "ForbiddenAttributesError" instead of it just throwing away the attributes.

2

2 Answers

1
votes

Merge is the way to go as far as I know. On the other hand, your merge is not working because .merge does not update the hash p, you can either do p = p.merge or use p.merge! which does modify p.

Also, depending on how nested your models are you might need .deep_merge instead of merge.

Hope that helps.

1
votes

Looks like this solution is working - just building an array and passing that to permit. I have no idea if this would be considered best practice

def update_params
    a = []
    if can? :update, Asset
      a += [:code, :description]
    end
    if can? :update, Ability::THING1
      a += [:some_nested_stuff => [:id, :quantity, :_destroy],
                   :some_other_nested_stuff => [:id, :quantity, :_destroy]]
    end
    ......
    params.require(:asset).permit(a)
  end