Reputation: 20844
I'm having a hard time trying to understand how to permit non model parameters.
I've read:
So, for a "normal" situation - let's say that I have a model Foo
which has just one attribute bar
:
# foo.rb
class Foo < ActiveRecord::Base
# bar, which is a integer
end
# views/foos/new.html.erb
<%= form_for @foo do |f| %>
<%= f.number_field :bar %>
<%= f.submit %>
<% end %>
#foos_controller.rb
def create
@foo = Foo.new(foo_params)
# ...
end
#...
private
def foo_params
params.require(:foo).permit(:bar)
end
So, when I submit the form, the Foo
will be created.
However, what if the bar
attribute has some logic behind it that combines some non model parameters? Let's say that bar
is the sum of two parameters (bar = bar_1 + bar_2
). Then the view and controller looks like:
# views/foos/new.html.erb
<%= form_for @foo do |f| %>
<%= f.number_field :bar_1 %>
<%= f.number_field :bar_2 %>
<%= f.submit %>
<% end %>
#foos_controller.rb
def create
bar_1 = params[:foo][:bar_1]
bar_2 = params[:foo][:bar_2]
if bar_1.present? && bar_2.present?
@foo = Foo.new
@foo.bar = bar_1.to_i + bar_2.to_i
if @foo.save
# redirect with success message
else
# render :new
end
else
# not present
end
end
So the question is, do I also need to permit the bar_1
and bar_2
parameters? If I do, how do I permit them?
Upvotes: 5
Views: 4122
Reputation: 3847
First Option: put the logic in your model:
Permit bar1
and bar2
:
def foo_params
params.require(:foo).permit(:bar1, :bar2)
end
Then handle this logic in your model:
class Foo < ActiveRecord::Base
attr_accessor :bar1, bar2
after_initialize :set_bar
def set_bar
self.bar = bar1 + bar2 if bar_1 && bar_2
end
end
Second Option: Create a formatted_params method:
# views/foos/new.html.erb
<%= form_for @foo do |f| %>
<%= f.number_field :bar_1 %>
<%= f.number_field :bar_2 %>
<%= f.submit %>
<% end %>
#foos_controller.rb
def create
@foo = Foo.new(formatted_params)
if @foo.save
# redirect with success message
else
# render :new
end
end
def permitted_params
params.require(:foo).permit(:bar_1, :bar2)
end
def formatted_params
bar1 = permitted_params.delete(:bar1)
bar2 = permitted_params.delete(:bar2)
permitted_params.merge(bar: bar1 + bar2)
end
Upvotes: 2
Reputation: 770
There is no need to permit bar_1 and bar_2 parameters unless you create them under foo. But in your case you are creating in under foo. The best solution is to create attr_accessor
# foo.rb
class Foo < ActiveRecord::Base
# bar, which is a integer
attr_accessor :bar_1, bar_2
end
# views/foos/new.html.erb
<%= form_for @foo do |f| %>
<%= f.number_field :bar_1 %>
<%= f.number_field :bar_2 %>
<%= f.submit %>
<% end %>
#foos_controller.rb
def create
bar_1 = params[:foo][:bar_1]
bar_2 = params[:foo][:bar_2]
if bar_1.present? && bar_2.present?
@foo = Foo.new
@foo.bar = bar_1.to_i + bar_2.to_i
if @foo.save
# redirect with success message
else
# render :new
end
else
# not present
end
end
Upvotes: 1
Reputation: 1484
If you want to access those two non-model parameter, you have to bind it with model by below code on your Foo
model
attr_accessor :bar_1, :bar_2
No need to permit it in
def foo_params
params.require(:foo).permit(:bar)
end
Note: Make sure you remove it from your params
, It will not raise any error, but give you a warning on rails console
like Unpermitted parameters: bar_1, bar_2
Upvotes: 4