Question

class OptionValue
    has_and_belongs_to_many :listings, join_table: 'listing_options'
    belongs_to :type

class Listing
    has_and_belongs_to_many :option_values, join_table: 'listing_options'
    accepts_nested_attributes_for :option_values

I've looked at several questions here on the same topic, however in all those questions the asker wants additional functionality on the relationship and goes with the :through instead. I am looking to add values to the join table using the accepts_nested_attributes.

A listing has an option value for each option type. After processing the params received from the form they look like this:

listing_params => { "option_values_attributes"=> [{"option_value"=>"3"}, {"option_value"=>"5"}, {"option_value"=>"9"}]}

Calling Listing.new(listing_params) in create gives the error message

Unpermitted parameters: option_values
ActiveRecord::UnknownAttributeError: unknown attribute: option_value

Other attributes are successfully saved to the new listing instance. I've also tried option_value_id as parameter with the same result, and including @listing.option_values.build in new doesn't make a difference. I could convert the relationship to a :through relationship, but I do not need that type of relationship and would expect the HABTM to be more efficient otherwise. Is there something else I'm missing in the parameters, or should I change the relationship type to :through?

edit - relevant controller code

def create
  *binding.pry*
  @listing = Spree::Listing.new(listing_params)
  # @listing.save
def new
  @listing = Listing.new
  @listing.option_values.build

def listing_params
  params[:listing][:option_values_attributes] = []
  ovs = params[:listing][:option_values].values
  ovs.each do |ov|
    params[:listing][:option_values_attributes] << {"option_value" => ov}
  end
  params.require(:listing).permit(permitted_listing_attributes)
end

def permitted_listing_attributes
  [ :listing_options_attributes => [[:option_value_id]]] ]
end

edit - I now believe adding to the join table via accepts_nested_attributes is not supported in rails. Passing the option value ids as such raises an error. When instantiating a new listing (below), passing the type_id does not raise an error, indicating that we could use the accepts_nested_attributes with HABTM to create new option values, but not for adding only to the join table.

Listing.new({state: "1", "option_values_attributes" => [{"type_id" =>"30"}] })
Was it helpful?

Solution

If you haven't already, take a look at the docs for accepts_nested_attributes.

You need to include the parameters for OptionValue you are wanting to update in the params for Listing.

Another resource other than the docs: an excellent railscasts.

Your notion that HABTM is "more efficient" than a has_many :through is false. In fact, if you dig into the way rails implements HABTM, you'll see that it just creates another has_many :through. An easy way to see this is to reflect_on_all_associations() for one of your classes. You won't see a has_and_belongs_to_many relationship but you will see an association for has_many :through a join table and a has_many for a relationship to the join table. If you know how to solve this problem using :through instead, just make the switch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top