-2

I'm trying to create rails form for a customer. They should select a city for the list of existing cities. But it is not being saved.

index.html.erb

<%= form_for @customer do |f| %>
  <div class="field">
    <%= f.label :first_name %><br>
    <%= f.text_field :first_name %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br>
    <%= f.text_field :last_name %>
  </div>
  <div class="field">
    <%= f.label :phone_number %><br>
    <%= f.text_field :phone_number %>
  </div>
  <div class="field">
    <%= f.label :city %><br>
    <%= f.select :city_id, City.all.map(&:name) %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

city.rb

class City < ActiveRecord::Base
  validates_presence_of :name
  has_many :customers
end

customer.rb

class Customer < ActiveRecord::Base
  validates_presence_of :first_name
  validates_presence_of :last_name
  validates_uniqueness_of :phone_number
  belongs_to :city
end

customer_controller.orb

  def create
    @customer = Customer.find_or_initialize_by(customer_params)

    respond_to do |format|
      if @customer.save
        format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
        format.json { render :show, status: :created, location: @customer }
      else
        format.html { render :new }
        format.json { render json: @customer.errors, status: :unprocessable_entity }
      end
    end
  end

  def customer_params
      params.require(:customer).permit(:first_name, :last_name, :phone_number, :city)
    end
Antarr Byrd
  • 24,863
  • 33
  • 100
  • 188

3 Answers3

1

Try modifying the customer_params to allow the city_id attribute, currently you have defined just city:

def customer_params
  params.require(:customer).permit(:first_name, :last_name, :phone_number, :city_id)
end

Try also adding the city id attribute to your form select tag, you're just mapping the name, you can easily achieve it by using pluck:

<%= f.select :city_id, City.all.pluck(:name, :id) %>

I'd recommend you to create an instance variable in your controller and then using it.

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
  • I see, the problem is in your select, you're just passing the name of the City, I've added that part to the answer @AntarrByrd, take a look. – Sebastián Palma Jul 30 '17 at 03:33
1

In your form, you use city_id

<div class="field">
  <%= f.label :city %><br>
  <%= f.select :city_id, City.all.map(&:name) %>
</div>

But in your controller you use city

def customer_params
  params.require(:customer).permit(:first_name, :last_name, :phone_number, :city)
end

Another bug might be that you're using the city model's name as the option's value, instead of the model's id, and as a result, and this string (instead of a numerical id) is passed to find_or_initialize_by.

yuchuan
  • 26
  • 4
1

I was able to fix it by using options_for_select

<%= f.select :city_id, options_for_select(City.all.map{ |city| [city.name, city.id]}) %>
Antarr Byrd
  • 24,863
  • 33
  • 100
  • 188
  • 1
    `pluck` would also do the trick, in a shorter version just get the name and id, as it's ActiveRecord the performarnce is in a query level, using map you get all the atributes and use only two. – Sebastián Palma Jul 30 '17 at 03:38