has_many通过表单中的访问连接表属性

时间:2016-07-20 23:35:47

标签: ruby-on-rails ruby forms has-many-through

我有以下型号:

class RandomExam < ActiveRecord::Base
  has_many :random_exam_sections
  has_many :sections, :through => :random_exam_sections
end

class Section < ActiveRecord::Base
  has_many :random_exam_sections
  has_many :random_exams, :through => :random_exam_sections

class RandomExamSection < ActiveRecord::Base
  belongs_to :random_exam
  belongs_to :section
end

这个想法是有一些配置来创建随机考试,所以这个表有助于选择你需要的部分,然后还选择每个部分的问题数量,这里是每个表的属性:

RandomExam:name(字符串),created_at(datetime),updated_at(datetime)

部分:name(字符串),created_at(datetime),updated_at(datetime)

RandomExamSection:random_exam_id(整数),section_id(整数),questions_number(整数)

正如您所看到的,每个部分的问题属性数在RandomExamSections表中,我想以从RandomExam控制器显示的形式访问它,这是我的表单:

<%= form_for (@random_exam) do |f|  %>
    <div class="row">

        <div class="input-field col s12">
            <%= f.label :name, 'Name' %>
            <%= f.text_field :name, placeholder: 'Enter the name of the       configuration' %>
        </div>

    </div>

    <% @sections.each do |section| %>

        <div class="row <%= dom_id(section) %>">
            <div class="col s4">
                <%= check_box_tag 'random_exam[section_ids][]',  section.id,
                @random_exam.section_ids.include?(section.id), id:     dom_id(section), class: "section-checkbox #{dom_id(section)}" %>
                <%= label_tag dom_id(section), (raw sanitize     section.name, tags: %w(h2 p strong em a br b i small u ul ol li     blockquote), attributes: %w(id class href)),
                class: "name #{dom_id(section)}" %>
            </div class="col s4">
            <div>
                <%= text_field_tag "random_exam[random_questions_numbers][#{section.id}][]", nil,
                                   :placeholder => 'Enter the number of questions' %>
            </div>

        </div>
    <% end %>

    <div class="form-group">
        <%= f.submit class: "btn waves-effect waves-light green"  %>
    </div>

<% end %>

我的控制器:

def create
  @random_exam = RandomExam.new(random_exam_params)
  if @random_exam.save
  assign_random_questions_number
  flash[:success] = 'Random configuration created successfully'
  redirect_to @random_exam
else
  flash.now[:danger] = @random_exam.errors.full_messages.to_sentence
  render 'new'
end

def assign_random_questions_number
  if params[:random_exam][:'random_questions_numbers'] == nil
    return
  end


params[:random_exam][:'section_ids'].each do |key, value|
  record = RandomExamSection.search_ids(@random_exam.id, key)

  record.each do |random_exam_section_record|
    number_of_questions = params[:random_exam][:'random_questions_numbers'][key].first.to_i
    random_exam_section_record.update(questions_number: number_of_questions)
  end
end

当我更新方法TypeError: nil is not a symbol nor a string

中的记录时,我收到了一个TypeError:assign_random_questions_number

当我在控制台上运行

时,甚至会出现此错误
random = RandomExamSection.first
random.update(questions_number: 10)

或者当我跑步时:

random = RandomExamSection.first
random.questions_number = 10
random.save

修改

我最终删除了RandomExamSection中的关联,并使用questions_number

在'assign_random_questions_number'中重新创建了该关联

感谢。

1 个答案:

答案 0 :(得分:1)

如果你使用nested_attributes,你可以这样做:

#form
<h4>Selected exams</h4>
<%= f.fields_for :random_exam_sections do |b| %>
  <%= b.hidden_field :section_id %>
  <%= b.label :selected, b.object.section.name %>
  <%= b.check_box :selected, { checked: !b.object.id.blank? } %>
  <br>
  <%= b.label :question_numbers %>
  <%= b.text_field :questions_number %>
 <% end %>

#RandomExamModel
class RandomExam < ApplicationRecord
  has_many :random_exam_sections, inverse_of: :random_exam
  has_many :sections, :through => :random_exam_sections

  accepts_nested_attributes_for :random_exam_sections, reject_if: :is_not_selected


  private
  def is_not_selected(attr)
    attr["selected"] == '0'
  end
end

# RandomExam
class RandomExamSection < ApplicationRecord
  belongs_to :random_exam
  belongs_to :section

  attr_accessor :selected
end

# Controller
# GET /random_exams/new
  def new
    @random_exam = RandomExam.new
    @random_exam.random_exam_sections.build(Section.all.map{|s| {section_id: s.id}})
  end

这个想法基本上是

- Build on controller the random_exam_sections to be selected
- Write a form that allows to you 'select' one option and assign the number
- Then, validate if the random_exam_section of a sections was selected (this why i made that `attr_accessor :selected`, i need a place to write if user select the exam_section)
- If was selected, save.

这里的技巧是在控制器上构建,然后在视图上选择并验证模型上的选定内容。如果您需要帮助,我在这里做了一个例子:https://github.com/afromankenobi/nested_attr_demo

要在创建random_exam_sections时添加部分,您应该使用javascript。也许这个railscast可以帮助你http://railscasts.com/episodes/196-nested-model-form-part-1