在has_many中添加对现有记录的引用:association

时间:2017-03-16 01:55:18

标签: ruby-on-rails ruby-on-rails-4

我希望有一个表单,它将现有记录添加到has_many中:通过使用Ruby on Rails 4搜索字段。

我的模型如下:

class Offering < ActiveRecord::Base
  has_many :students, through: :enrolments
  has_many :enrolments
end

class Enrolment < ActiveRecord::Base
  belongs_to :offering
  belongs_to :student
end

class Student < ActiveRecord::Base
  has_many :offerings, through: :enrolments
  has_many :enrolments
end

在我的产品的显示页面上,我想要一个“按学生ID添加学生”表格。用户可以输入学生的学生ID(即铁路记录的ID),并提交以添加关联。

(最好是在输入有效的学生证时页面会在提交之前自动显示即将添加的学生的全名)

但我相当新手,而且我不确定如何设置它。我的期望是这样的:

<h4>Add Student</h4>
<%= form_for @offering do |f| %>
  <p>
    Student ID: <%= f.text_field @sid %><br>
  </p>
  <p>
    <%= f.submit "Add Student" %>
  </p>
<% end %>

其中sid是一个局部变量,我可以用来在控制器中查找学生并使用@offering.students << Student.search()添加。

但我只是不确定,并希望得到任何帮助。谢谢!

1 个答案:

答案 0 :(得分:0)

我遇到了类似的挑战并使用simple_form gem和一个小Jquery来解决它。

我的模型中的has_many:through关联具有与您相同的结构,但在父模型和连接模型中包含“accepts_nested_attributes_for”类方法。在你的情况下,它将是:

class Offering < ActiveRecord::Base
  has_many :students, through: :enrolments
  has_many :enrolments
  accepts_nested_attributes_for :enrolments
end

class Enrolment < ActiveRecord::Base
  belongs_to :offering
  belongs_to :student
  accepts_nested_attributes_for :students
end

class Student < ActiveRecord::Base
  has_many :offerings, through: :enrolments
  has_many :enrolments
end

我还需要做一些事情来根据另一个输入的值动态创建关联(在您的情况下,输入学生ID的文本输入):

<强> 1。将关联表单助手添加到我的视图中。使用simple_fields_for和关联助手在“产品#show”视图中“嵌套”Enrollment和Student表单字段(当我在父模型的_form中包含以下代码时,这对我有用)部分,即使您将其添加到show.html.erb文件中):

<%= simple_form_for @offering do |f| %>
    <h4>Add Student</h4>
    <%= f.simple_fields_for :enrolments do |e| %>
        <p>Student ID: <%= text_field_tag 'sid' %><br><span id="student_name"></span></p>
        <span style="display:none;"><%= e.association :student, collection: [] %></span>
    <% end %>
    <p><%= f.submit "Add Student" %></p>
 <% end %>

<强> 2。创建一个AJAX调用以动态写入视图。向父模型的js.coffee文件添加ajax调用,以使用文本输入的值动态创建关联:

# offering.js.coffee

$('form').on 'blur', '[id="sid"]', (event) ->
        $.ajax
          url: '/set_student_id/'
          type: 'GET'
          dataType: 'json'
          json: true
          data: {student_id: $("input[id='sid']").val()}
          success: (data) ->
            $("[id$='student_id']").html(data.sid)
            $("[id='student_name']).html(data.name)
          error: (data) ->
            console.log "error"

第3。添加一个动作来处理父模型控制器中的ajax调用。使用与动作的ajax调用中的“url”值相同的名称(并确保允许连接和子模型属性): / p>

# offerings_controller.rb

def set_student_id
    student = Student.find_by(sid: params[:student_id])
    @sid = "<option value='#{student.id}' selected='selected'>#{student.name}</option>"
    respond_to do |format|
        format.json { render json: {sid: @sid, name: student.name} }
    end
end

def offering_params
    params.require(:offering).permit(enrolments_attributes:[:id, :student_id, students_attributes: [:id, :name]])
end

<强> 4。更新ajax回调的/config/routes.rb文件。确保您在ajax调用中包含的'url'值被路由到父模型控制器中的正确操作:

get "/set_student_id/", to: "offerings#set_student_id"

Simple Form关联助手默认创建一个选择列表。此代码应动态添加与在列表中作为选定选项输入的sid匹配的Student,并在输入失去焦点(jquery中的blur事件)后动态显示sid表单输入下面的Student name。

希望这有帮助。