Reputation: 1005
I'm trying to put into practise using skinny controllers and fat models, however in order to do this I find myself needing to pass additional variables into the .create method.
So for example where I had:
@app = App.new(app_params)
def app_params
params.require(:app).permit( :name, :description)
end
Now I want to also pass along say, a session held user_id, and a reference to a permission group. So hopefully something like the following pseudo code:
@app = App.create(app_params, session[:user_id], app_permission_id)
The user_id and app_permission_id would not be persisted but would be available I'd hope somewhere like in the after_create callback within the model, so I can then do some further work, for example creating a log entry of the creation, associated to the calling user.
I'm not so keen on just adding them in the form as hidden fields (to hide implementation from users). I think there is a possible approach using .merge? if that's the way, the I guess I pull them out using a virtual attribute.
Any advise on the best/cleanest approach would be much appreciated. I think I'd prefer to override the .create method somehow (but only in terms of the cleanest implementation from the controller side).
Upvotes: 5
Views: 2843
Reputation: 76784
The two answers describing .merge
are correct; let me explain why
--
Params
When processing your params at controller level, and handling with strong_params
, Rails basically "passes" the data through to your model, like this:
"params" => {
"app" => {
"name" => "data",
"description" => "data",
}
}
This is what the typical form_for
params object sends through to your controller. When you pick up the data through the strong_params
method, you basically just "permit" the various pieces of data to pass through to the model.
Remember, strong_params
are designed to help prevent mass_assignment
, which means the method is designed to only send particular params through to your model.
--
Fix
If you want to append extra data to each model request - you'll have to use merge
:
def app_params
params.require(:app).permit(:name, :description).merge(user_id: session[:user_id], app_permission_id: app_permission_id)
end
Upvotes: 1
Reputation: 3422
If you are app_params should always contain user_id and app_permission_id
you should do it this way
def app_params
params.require(:app).permit( :name, :description).merge(user_id: session[:user_id], app_permission_id: app_permission_id)
end
Else if it should not contain this all the time
you should do it this way
app_params.merge(user_id: session[:user_id], app_permission_id: app_permission_id) #as mentioned by Vapire in his answer
Upvotes: 6
Reputation: 4588
Yes, this should be possible with merge
def create
@app = App.new(app_params.merge(user_id: session[:user_id], app_permission_id: app_permission_id))
end
Of course you'd need virtual attributes user_id
and app_permission_id
in your model.
Also see this answer.
Upvotes: 1