2

This is driving me crazy. Probably I'm overlooking something obvious, but I've read all other posts on the same topic and can't solve the problem. Thanks in advance for any help.

I have a model Klasse and a Model Klp. An instance of klasse has many klps. I would like to create klp in the same form as klasse. I've set this up using form_with and fields_for, and in klasses_controller.rb I have 3.times { @klasse.klps.build } But this iteration does not seem to work. The fields_for block is only shown once instead of 3 times.

The form in new.html was created following the rails "getting started" guide, and the fields_for block following the "form helpers" guide.

Here is my code:

app\models\klasse.rb:

class Klasse < ApplicationRecord
    has_many :klps
    has_many :people, :through => :klps
    accepts_nested_attributes_for :klps, allow_destroy: true, :reject_if => :all_blank

    validates :name, presence: true,
                  length: { minimum: 1 },
                  uniqueness: true

    validates :klp_std_soll, presence: true,
                  length: { minimum: 1 }

   def klp_std_ist
       self.klps.sum("std")
   end

end

app\models\person.rb

class Person < ApplicationRecord
  has_many :klps
  has_many :klasses, :through => :klps

  validates :name, presence: true,
                  length: { minimum: 1 },
                  uniqueness: true
  validates :vorname, presence: true,
                  length: { minimum: 1 }

  def last_and_first_name
    "#{name}, #{vorname}"
  end

end

app\models\klp.rb

class Klp < ApplicationRecord
    belongs_to :klasse
    belongs_to :person
end

app\controllers\klasses_controller.rb

class KlassesController < ApplicationController

    def new
        @klasse = Klasse.new
        3.times { @klasse.klps.build }
    end

    private
    def klasse_params
        params.require(:klasse).permit(:name, :klassentyp_id, :klp_std_soll, klps_attributes: [:id, :person_id, :std, :_destroy])
    end

end

app\controllers\klps_controller.rb

class KlpsController < ApplicationController

    def new
        @klp = Klp.new
    end

    private
    def klp_params
        params.require(:klp).permit(:klasse_id, :person_id, :std)
    end
end

app\views\klasses\new.html.erb

<%= form_with scope: :klasse, url: klasses_path, local: true do |form| %>

     <ul>
         <%= form.fields_for :klps do |klps_form| %>
            <p>
                <%= klps_form.label :person %>
                <%= klps_form.collection_select :person_id, Person.all, :id, :last_and_first_name %>
                <%= klps_form.label :std %>
                <%= klps_form.text_field :std %>
            </p>

        <% end %>
    </ul>

    <p>
        <%= form.submit %>
    </p>
<% end %>
4
  • I am not sure I understand your question. Are you trying to create three iterations of your form.fields_for block? Commented Nov 4, 2017 at 15:39
  • @TomAranda: Yes. I want three sets of these input fields. Commented Nov 5, 2017 at 8:37
  • class Person < ApplicationRecord has_many :klps has_many :klasses, :through => :klps end please verify person.rb Commented Nov 5, 2017 at 9:32
  • @NatarajaB: I posted person.rb above. Commented Nov 5, 2017 at 20:53

3 Answers 3

1

Try setting your collection of klps to an instance variable that you can then pass as an explicit "record object" argument to the fields_for method:

apps/controllers/klasses_controller.rb

def new
  @klasse = Klasse.new
  @klps = 3.times { @klasse.klps.build }
end

app\views\klasses\new.html.erb

<%= form.fields_for :klps, @klps do |klps_form| %>
  ... your form...
<% end %>

See also: How do I pass an array to fields_for in Rails?

Reference: https://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for

Sign up to request clarification or add additional context in comments.

Comments

0

I am giving an example see

customer.rb

class Customer < ApplicationRecord
   has_many :addresses, dependent: :destroy
   accepts_nested_attributes_for :addresses, allow_destroy: true
end

address.rb

class Address < ApplicationRecord
   belongs_to :customer
end

customers_controller.rb

class CustomersController < ApplicationController
  def new
    @customer = Customer.new
    3.times {
      @customer.addresses.build //You can use @customer.addresses.new
    }
  end
end

  def customer_params
    params.require(:customer).permit(:id, :name, addresses_attributes:[:id,:country, :state])
  end

new.html.haml

= simple_form_for @customer do |f|
  = f.input :name, label: false, wrapper: false, input_html: { class: "gui-input"}, placeholder: "Customer Name"
  = f.fields_for :addresses do |a|
    = render 'addresses/fields', a: a

view/addresses/_fields.html.haml

= a.input :country, as: :select, label:false, :wrapper => false, prompt: "Select country"

= a.input :city, label:false, :wrapper => false, input_html: {class: "gui-input", maxlength: 80, minlength: 2}, placeholder: "City"

for more info

https://www.pluralsight.com/guides/ruby-ruby-on-rails/ruby-on-rails-nested-attributes

3 Comments

Thank you. Using @customer.addresses.new instead of .build does not make a difference. Other than this, the only difference to my code that I can find is using form_for (or simple_form_for) instead of form_with. Using form_for instead of form_with also does not help.
@JRinCH You have done some mistake in association, please verify u r has_many through association
Pls see original post, I added person.rb there.
0

use

<%= form.fields_for :klps_attributes do |klps_form| %>

2 Comments

could you try form_for instead of form_with too.
Thank you. Using :klps_attributes instead of :klps does not make a difference. Also, using form_for instead of form_with does not help. Am I overlooking something obvious?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.