0

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.

Chris Farmer
  • 24,974
  • 34
  • 121
  • 164
  • What does your `ProductController` look like? Typically you'll need an `if @product.save` block to catch errors. Then you can update the view. with error messages. – t56k Dec 03 '18 at 19:59
  • Yes, I am catching any errors in the @product.save and can report them after the fact. My question is mostly about the distinction between `thing` and `thing_id` in associations and in presence validators. – Chris Farmer Dec 03 '18 at 20:03

2 Answers2

2

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.

arieljuod
  • 15,460
  • 2
  • 25
  • 36
1

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.

t56k
  • 6,769
  • 9
  • 52
  • 115