How can i set the default values of controller parameters?
Asked Answered
A

4

8

I have a customers table on my database and a column named as "last_updated_by" . I want to add current users name as a plain text in this field.

I got devise installed on my app so it gives me the current_user parameter.I tried to add current_user.name to the customers_controllers permitted parameters but it did not worked.

1-
def customer_params
params.require(:customer).permit(:name, :last_updated_by=>current_user.name)
end

2-
def customer_params
  params[:last_updated_by] = current_user.name
  params.require(:customer).permit(:name, :last_updated_by)
end

3-
def customer_params
  last_updated_by = current_user.name
  params.require(:customer).permit(:name, :last_updated_by=>current_user.name)
end

How can i set some default values in controller.

Amrita answered 23/12, 2018 at 13:14 Comment(2)
You should explain more why you need a default value in your controller, because the best/easy way to set default value to a param with rails is on modelDynamiter
I explained it in the main post. I want to add last_updated_by information automatically.Amrita
R
1

If you need the last_updated_by param to go within the customer_params (customer hash key for ActionController::Parameters), then:

before_action :set_last_updated_by_param, only: :create

private

def set_last_updated_by_param
  params[:customer][:last_updated_by] = params.dig(:customer, :name)
end

The before_action callback adds the new key last_updated_by on the customer params only before the create action is executed.

Notice, no need to modify the customer_params to permit it.


As showed by @JohanWentholt, with_defaults seems to be the best way. Go for it.

Waiting the OP chooses the correct answer.

Ringworm answered 23/12, 2018 at 13:34 Comment(6)
Keep in mind that this doesn't set a default value. If a value is already present in the params it is overwritten. Use the ||= assignment operator instead.Dallis
Appreciated for answers but i am getting the error "undefined method `name' for :current_user:Symbol".Amrita
Okay i changed params[:customer][:last_updated_by] = params.dig(:customer, :name) to params[:customer][:last_updated_by] = current_user.name and it worked. But i am still curious why i can't define it in the permitted_params directly.Amrita
The answer still doesn't set a default this way. If you provide the ?customer[last_updated_by]=Some+Name parameter it will be overwritten by the set_last_updated_by_param method. The reason that no default is set when using permit is simply because the permit method doesn't allow you to set defaults.Dallis
@JohanWentholt Default values for permitted params can be set via .with_defaultsSane
with_defaults seems to be the best way. Go ahead for it.Stryker
D
16

Since you're asking about setting a default value I suggest using the with_defaults method, which is simply an (more expressive) alias for reverse_merge.

def customer_params
  params
    .require(:customer)
    .permit(:name, :last_updated_by)
    .with_defaults(last_updated_by: current_user.name)
end

reverse_merge does the same thing as merge, the only difference is what happens for conflicting keys. merge uses the value of the hash passed through the parameters, whereas reverse_merge prefers the value of the receiver.

params = { a: 1, b: 2 }
defaults = { a: 4, c: 5 }
params.merge(defaults)         #=> { a: 4, b: 2, c: 5 }
params.reverse_merge(defaults) #=> { a: 1, b: 2, c: 5 }
#       ^ aka with_defaults
Dallis answered 23/12, 2018 at 14:46 Comment(0)
D
2

If you need a default value only if params[:last_updated_by] is not present in the body of your request, you can try:

def create
  params[:last_updated_by] = params[:last_updated_by].blank? ? 'Default value' : params[:last_updated_by]
  Customer.new(params)
  # finish your controller method
end

def customer_params
  params.require(:customer).permit(:name, :last_updated_by)
end

Now if you need to set a default value on every create and update if last_updated_by is nil, you should do this on Customer model:

after_save :set_last_updated_by

def set_last_updated_by
  self.last_updated_by = self.last_updated_by.blank? ? 'Default value' : self.last_updated_by
end
Dynamiter answered 23/12, 2018 at 14:34 Comment(1)
params[:last_updated_by] = params[:last_updated_by].blank? ? 'Default value' : params[:last_updated_by] can be written as params[:last_updated_by] ||= 'Default value' Nothing wrong with either version, just giving an alternative.Sane
R
1

If you need the last_updated_by param to go within the customer_params (customer hash key for ActionController::Parameters), then:

before_action :set_last_updated_by_param, only: :create

private

def set_last_updated_by_param
  params[:customer][:last_updated_by] = params.dig(:customer, :name)
end

The before_action callback adds the new key last_updated_by on the customer params only before the create action is executed.

Notice, no need to modify the customer_params to permit it.


As showed by @JohanWentholt, with_defaults seems to be the best way. Go for it.

Waiting the OP chooses the correct answer.

Ringworm answered 23/12, 2018 at 13:34 Comment(6)
Keep in mind that this doesn't set a default value. If a value is already present in the params it is overwritten. Use the ||= assignment operator instead.Dallis
Appreciated for answers but i am getting the error "undefined method `name' for :current_user:Symbol".Amrita
Okay i changed params[:customer][:last_updated_by] = params.dig(:customer, :name) to params[:customer][:last_updated_by] = current_user.name and it worked. But i am still curious why i can't define it in the permitted_params directly.Amrita
The answer still doesn't set a default this way. If you provide the ?customer[last_updated_by]=Some+Name parameter it will be overwritten by the set_last_updated_by_param method. The reason that no default is set when using permit is simply because the permit method doesn't allow you to set defaults.Dallis
@JohanWentholt Default values for permitted params can be set via .with_defaultsSane
with_defaults seems to be the best way. Go ahead for it.Stryker
S
1

As method params.permit method is used to filter the parameter you want to create the object with, you can use any of the solution given above, but if you want to modify params in def customer_params then i would like to modify your 2nd solution

def customer_params
  params[:customer][:last_updated_by] = current_user.name 
  params.require(:customer).permit(:name, :last_updated_by)
end
Seventieth answered 25/12, 2018 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.