Chris Farmer
Chris Farmer

Reputation: 25415

How to show required form field for association in rails?

I'm new to rails, and I'm not sure how to set up a combobox so that it can be shown as "required" in the browser. I have a Product and a Location, and location should be required in a product:

class Product < ApplicationRecord
  belongs_to :location
  validates :location, presence: true
end

class Location < ApplicationRecord
  has_many :products
end

In my new product form, I have a helper that shows that the field is required, but I'm not sure how best to do that with this associated location. When I try to map it to the :location attribute like this:

<%= form_for @product do |f| %>
  <%= show_label f, :location %>
  <%= f.collection_select :location, @locations, :id, :name, include_blank: true %>
  <%= f.submit %>
<% end %>

# helper
def show_label(f, attr)
  required = f.object.class.validators_on(attr)
                 .any? { |v| v.kind_of?(ActiveModel::Validations::PresenceValidator) }
  label = attr.to_s + required ? '*' : ''
  label
end 

...the show_label helper correctly sees that :location is required, but the model itself fails to validate after the form is posted because location here is a string (the :id of the location) rather than an actual Location.

When I instead use :location_id:

<%= f.collection_select :location_id, @locations, :id, :name, include_blank: true %>

then show_label doesn't see that :location_id is a required attribute so I don't get the required field annotation, but the location gets correctly saved when the model is saved.

What's the right way to render a combobox so I can both recognize if it's a required field AND allow my controller to save my Product? I feel like I'm probably missing something that competent Rails people all just know.

Upvotes: 0

Views: 470

Answers (2)

t56k
t56k

Reputation: 7001

There are a bunch of posts on the differences between validating the association and validating the _id column, but the rough idea should be to validate both the _id column and the association.

Upvotes: 1

arieljuod
arieljuod

Reputation: 15838

Try using validates :location_id, presence: true. It's not the same as the other validation (you could set an id that does not exist, it will be valid because it's present but it will be an invalid location), so leave the :location validation too.

Upvotes: 2

Related Questions