Good day, need help. Help create a view. There is a document form, it has 3 parameters: Product Type, Product , Product Brand . The form should allow you to add different brands of the same product at the same time.

That is, there must be something like this:

  1. Field: Product Type
  2. Field: Product
  3. Field: Product Brand
  4. Link to add a new Brand, that is, link_to_add_association: brand of the same Product, paragraph 2

New to Rails, so do not judge strictly, thanks in advance for your help.

Below is the application logic:

class Document < ActiveRecord::Base (id, name) has_many :product_documents end class BrandOfProductDocument < ActiveRecord::Base (id, product_id, document_id) belongs_to :document belongs_to :brand_of_product end class BrandOfProduct < ActiveRecord::Base (id, brand_id, product_id) belongs_to :brand belongs_to :product end class Product < ActiveRecord::Base (id, name, product_type_id) belongs_to :product_type end class ProductType < ActiveRecord::Base (id, name) end class Brand < ActiveRecord::Base (id, name) end 

Document_form.rb:

 class DocumentForm < ActiveForm::Base self.main_model = :document association brand_of_product_document do attribute :brand_of_product_id association :brand_of_product do association :product do attribute :name association :product_type do attribute :name end end association :brand do attribute :name end end end end 

ActiveForm :: Base is from the actionform form

But the form interface itself:

enter image description here

enter image description here

To be more specific, problems with the associations in the view, how to build correctly, tried to follow this example https://github.com/m-Peter/nested-form-examples/tree/master/full-example/after/app/ views / projects .

In the file _form.html.erb I write:

 <div id="tags"> <%= f.fields_for :brand_of_product_document do |bpd| %> <%= render 'brand_of_product_document_fields', :f => bpd%> <% end %> <%= link_to_add_association 'add brand_of_product_doc', f, :brand_of_product_document %> </div> 

In the _brand_of_product_document_fields.html.erb file , what to write is not clear, since my case is not quite similar to the above example.

  • 1. ActiveForm::Base is from which gem? 2. Π€ΠΎΡ€ΠΌΠ° Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ‚ΡŒ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ Ρ€Π°Π·Π½Ρ‹Π΅ ΠΌΠ°Ρ€ΠΊΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚Π° ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ. Can you tell more about this? At least you can sketch a shape. 3. The eternal question. What exactly does not work? - anoam
  • Here I added info, tried to explain as much as possible :) - user3094306
  • Good people respond, send me the right way - user3094306
  • Virtually any solution in Rails with editing several models at once is a very voluminous and ugly crutch, primarily because it requires additional measures on the client. Which, in turn, suggests a pure client solution and an API-like server part. It's just much easier to do and realize, although it requires you to become familiar with a large number of technologies. - D-side

1 answer 1

Unfortunately, I do not know such a heme as an actionform . Now I found it on a githaba, but it's strange. I would not recommend it.

I didn’t understand the associations to the end. I think that what I understood should be enough for an answer, but I apologize if, nevertheless, I am going to the side.

No need to try to reproduce the structure of the database on the form. The form must be flat, even if it changes the data in 10 tables. It’s just more confusion. FormObject will help implement such a form. (By the way, they even recommend using them in the style-guides )

 class DocumentForm include ActiveModel::Validations include ActiveModel::Conversion include Virtus.model def self.model_name Document.model_name end attribute :product_type_id attribute :product_id attribute :brand_ids, Array # Π’ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ ΠΊΠ°ΠΊΠΈΠ΅ Π½ΡƒΠΆΠ½Ρ‹. НапримСр Ρ‚Π°ΠΊ: validates :product_type_id, presence: true validates :product_id, presence: true def persisted? # ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для создания # для рСдактирования потрСбуСтся модификация false end def save return false unless valid? document = Document.new document.product_type = ProductType.find(product_type_id) document.product = document.product_type.products.find(product_id) document.brands = Brand.where(id: brand_ids) document.save end end 

In the controller:

 def new @form = DocumentForm.new end def edit @form = DocumentForm.new(permitted_params) if @form.save redirect_to documents_path else rednder action: :new end end #... private def permitted_params params.require(:document).permit(:product_type_id, :product_id, brand_ids: []) end 

On the view:

 <%= form_for @form do |form| %> <%= form.select :product_type_id, ProductType.all.collect { |p| [ p.name, p.id ] } %> <%= form.select :product_type_id, Product.all.collect { |p| [ p.name, p.id ] } %> <%= form.select :brand_ids, Brand.all.collect { |p| [ p.name, p.id ] }, {}, multiple: true %> <% end %> 

An example was made using Virtus . In order to ensure the coherence of the lists (select only brand products) and the ability to add more fields for selecting brands by button, you need to pee / search components in JavaScript. But it already pulls on a separate question.