-->

Rails 3.2 Create Parent Model from Child View

2019-02-25 19:14发布

问题:

I'm having a difficult time understanding how to do this. I have two models, a project, and a course.

#project.rb
belongs_to :course
attr_accessible :course_id, :course
accepts_nested_attributes_for :course, reject_if: lambda { |a| a[:course_id] == 0 }

#course.rb
has_many :projects

On the Projects#new page (child object), I want to type in the name of a new course and have it create the parent object.

Here's my attempt in the view, but it doesn't seem to be working correctly.

= form_for [@user, @project] do |f|

  # Other fields

  = fields_for :course do |builder|
    = builder.label :name, 'Course Name'
    = builder.text_field :name

  = f.submit

I'll be using this parent object later to create more projects, but for now, let's assume it doesn't exist.

UPDATE 1 I've modified my fields_for to be (as per Ryan's request):

= form_for [@user, @project] do |f|

  # Other fields

  = f.fields_for :course do |builder|
    = builder.label :name, 'Course Name'
    = builder.text_field :name

  = f.submit

I'm using haml, so the = should be displaying, but the fields for does not even show up on the page, or in the generated html. Any clue as to why that is? (The submit button does display)

UPDATE 2 I've found a potential solution, but I'm not sure if it's the correct way of approaching this. In the controller, I need to build a course for the fields_for to show up.

# ProjectsController
def new
  @project  = @user.projects.new
  @project.build_course
end

# project.rb
attr_accessible :course_attributes
# So yes, I now see what you were talking about, regarding the course_attributes

回答1:

You should be using the form builder to build out your object, rather than just fields_for by itself.

You have this:

= fields_for :course do |builder|

Where you should have this:

= f.fields_for :course do |builder|

The difference is that by calling it on the initial form builder, Rails will check to see if there is a course_attributes= method on the object from the initial form_for call (in this case, that'd be @project) and if there is then it'll define the fields inside this form as being course_attributes.

Go ahead and inspect the form before and after this change, just to see. I'll wait.

This is made possible by the accepts_nested_attributes_for call in your model. It's this method that defines the course_attributes= method that allows for the nested attributes to work. Once you create the project, it should then also create the course.

Also, no need to make course_id an accessible attribute, as your form's not going to be setting that.



回答2:

I used gem 'dynamic_form'. faculty_list(id, faculty_name) table contains names of faculties.

<%= f.select :faculty, options_from_collection_for_select(@faculty_list, 'id', 'faculty_name', @faculty.faculty.to_i) %>