Vucko
Vucko

Reputation: 20844

RoR permitting non model parameter

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

Answers (3)

lcguida
lcguida

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

sohail khalil
sohail khalil

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

hgsongra
hgsongra

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

Related Questions