0

I'm having almost exactly the same problem as here: Rails has_many :through saving additional fields

However I can't figure out what's missing in my code. The basic structure is following: there are Products and they may have additional services (like cleaning or sharpening). The basic price for each service is same, however products may have different coefficients. Let's say, Product 1 may have sharpening basic price * 1.5 and Product 2 may have sharpening basic price * 2. The join table is called somewhat stupid - servization, I couldn't figure out a decent name.

products_controller.rb:

def update
  @product.update!(product_params)
  redirect_to @product
end

def product_params
    params.require(:product).permit(
    :title, :description, :advertising_text, :fancy_quote, :hot, :hotpic, :product_size_ids, 
    { volume_ids: [] }, { color_ids: [] }, { addservice_ids: [] }, :category_id, :subcategory_id, 
    options_attributes: [:size, :weight, :price, :material, :product_id],
    images_attributes: [ :image, :product_id ],
    servizations_attributes: [:coefficient, :product_id, :addservice_id]
    )
end

product model (i cut out the irrelevant parts) :

class Product < ActiveRecord::Base
 has_many   :servizations
 has_many   :addservices, through: :servizations

 accepts_nested_attributes_for :servizations

 before_destroy :ensure_not_referenced_by_any_line_item

end

additional service model:

class Addservice < ActiveRecord::Base
    has_many :servizations
    has_many :products, through: :servizations
end

servization model

class Servization < ActiveRecord::Base
    belongs_to :product
    belongs_to :addservice
end

Here is my edit.html.haml:

=form_for @product do |f|
                =f.label 'Title'
                =f.text_field :title
                %p
                =f.label 'Colors'
                =collection_check_boxes(:product, :color_ids, Color.all, :id, :value )
                %p
                =f.label 'Additional services'
                =collection_check_boxes(:product, :addservice_ids, Addservice.all, :id, :title)
                =f.fields_for :servization do |s|
                    =s.label 'Coefficient'
                    =s.text_field :coefficient
                %p
                    =f.submit class: 'btn btn-default'

I have no issues saving plain services or just the colors, however when I try to edit and save the coefficient, then I receive following error:

Processing by ProductsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"jLN59PIOgpaIQtg2/rVYcK/xUOCFzSMLosfUhOslY9tNNhjFbh16Aa1/qT/8u7LHuhNTLGr2SB7b/BitekuDJQ==", "product"=>{"title"=>"Power MI", "color_ids"=>["1", "2", "3", ""], "addservice_ids"=>["1", ""], "servization"=>{"coefficient"=>"1.5"}}, "commit"=>"Update Product", "id"=>"7"}
  Product Load (0.3ms)  SELECT  "products".* FROM "products" WHERE "products"."id" = $1 LIMIT 1  [["id", 7]]
Unpermitted parameter: servization

Servization structure:

Servization(id: integer, product_id: integer, addservice_id: integer, coefficient: float, created_at: datetime, updated_at: datetime)

I don't get it... my options are saved well, images too. But additional services refuse to save.

Edit 1: I think I might be close to the solution. The problem is the correct linking in the form. This is what I came up with so far:

    =form_for @product do |f|
        %p
            =f.label "Additional Services"
        %br
        -Addservice.all.each do |addservice|
            =check_box_tag "product[addservice_ids][]", addservice.id, @product.addservice_ids.include?(addservice.id)
            =addservice.title
            =text_field_tag "product[servizations][coefficient][]", addservice.servizations.where(product_id: @product.id)[0].coefficient
            %br
        %p
            =f.submit class: 'btn btn-default'

This is the patch request:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"wD8uMSu0TxvumAWcs1V6GtAFeNgYhbEPEh8HuV8RWucBuk8At6e3jMuldJWxW5Ctxed7FPe+2hprJMuQzn+6GQ==", "product"=>{"title"=>"Флешеченка на тристапяцот гигов", "color_ids"=>["1", "2", "3", ""], "addservice_ids"=>["1", "2"], "servizations"=>{"coefficient"=>["4", "5"]}}, "commit"=>"Update Product", "id"=>"5"}

However now I'm getting again

Unpermitted parameter: servizations

Error

Community
  • 1
  • 1
mohnstrudel
  • 639
  • 8
  • 22
  • You're getting an unpermitted parameter error from the controller. Have you included servization in your strong params method in the controller? Can you show your code for products_controller? – margo Sep 06 '15 at 16:02
  • The products controller code is right at the beginning, I think it is included correctly. – mohnstrudel Sep 06 '15 at 19:08

1 Answers1

1

The problem is here in this line

=f.fields_for :servization do |s|

which should be

=f.fields_for :servizations do |s|

Update:

You should permit :id for update to work correctly

def product_params
    params.require(:product).permit(
    :title, :description, :advertising_text, :fancy_quote, :hot, :hotpic, :product_size_ids, 
    { volume_ids: [] }, { color_ids: [] }, { addservice_ids: [] }, :category_id, :subcategory_id, 
    options_attributes: [:size, :weight, :price, :material, :product_id],
    images_attributes: [ :image, :product_id ],
    servizations_attributes: [:id, :coefficient, :product_id, :addservice_id]
    )
end
Pavan
  • 33,316
  • 7
  • 50
  • 76
  • First of all - thank you! While the basic saving seems to work now, I have further issues - on each update there are double as many fields for coefficient displayed as before - http://take.ms/NvFBa Besides, the records are not created for a particular check box value - #, # – mohnstrudel Sep 06 '15 at 19:31
  • Next records: #, # What I basically want - to save an additional parameter to each check box from a check box collection. – mohnstrudel Sep 06 '15 at 19:32
  • I found a similar question without an answer - http://stackoverflow.com/questions/30306668/passing-extra-attributes-to-join-table-when-populating-the-form-with-collection And further one, but it didn't help me - http://stackoverflow.com/questions/9174513/rails-has-many-through-form-with-checkboxes-and-extra-field-in-the-join-model (and this one seems rather over complicated to be honest) – mohnstrudel Sep 06 '15 at 19:57
  • I found this article - https://hackhands.com/building-has_many-model-relationship-form-cocoon/ - and in the comments they say you have to white-list the id for - in my case - servizations_attributes, because if you don't, rails will generate new records. Could you please update your answer with this information, so I can accept it? – mohnstrudel Sep 08 '15 at 07:06