Ruby on Rails - 如何属于很多?

时间:2016-01-13 03:15:34

标签: ruby-on-rails

我有一个名为Report的表,另一个名为Phases。假设我有10 phases,我想在报告表单上列出所有phases的复选框。如何收集已检查的项目并将该数据存储在数据库中?

我是否需要拥有phase_one:integer phase_two:integer phase_three:integer等列,然后撤回非空的列?或者我可以以某种方式将x阶段的ID存储在一列中并将这些ID拉回到数组中吗?

2 个答案:

答案 0 :(得分:2)

要澄清NateSHolland的答案,如果phases已预定义,可以使用has_and_belongs_to_many

#app/models/report.rb
class Report < ActiveRecord::Base
   has_and_belongs_to_many :phases
end

#app/models/phase.rb
class Phase < ActiveRecord::Base
   has_and_belongs_to_many :reports
end

这样您就可以从表单中填充phase_idscollection_singular_ids)属性:

#config/routes.rb
resources :reports

#app/controllers/reports_controller.rb
class ReportsController < ApplicationController
   def new
      @report = Report.new
      @phases = Phase.all
   end

   def create
      @report = Report.new report_params
      @report.save
   end

   private

   def report_params
      params.require(:report).permit(:phase_ids)
   end
end

#app/views/reports/new.html.erb
<%= form_for @report do |f| %>
   <%= f.collection_check_boxes :phase_ids, @phases, :id, :name %>
   <%= f.submit %>
<% end %>

这将允许您指定报告具有哪些阶段,但不会有任何更改。

我认为你做得更好的是使用has_many :through,允许你定义你引用的phase

#app/models/report.rb
class Report < ActiveRecord::Base
   has_many :progress
   has_many :phases, through: :progress

   accepts_nested_attributes_for :progress #-> define level
end

#app/models/progress.rb
class Progress < ActiveRecord::Base
   #id report_id phase_id phase_lvl created_at updated_at
   belongs_to :report
   belongs_to :phase
end

#app/models/phase.rb
class Phase < ActiveRecord::Base
   has_many :progress
   has_many :reports, through: :progress
end

这里的重要因素是phase_lvl列 - 我的理解是您有某些&#34;级别&#34;你的阶段将成为其中的一部分。我无法正确描述它,但为了给你上下文,你会有类似......

  
      
  • 报告已编写(第5阶段)
  •   
  • 报告发布(第3阶段)
  •   
  • 报告已发送(第15阶段)
  •   

以上将使您能够定义哪个&#34;等级&#34;每个阶段表示。我认为这是你正在寻找的区别。

实施起来会有点棘手,但值得:

#app/controllers/reports_controller.rb
class ReportsController < ApplicationController
   def new
      @report = Report.new
      @phases = Phase.all
      10.times do 
         @report.progress.build
      end
   end

   def create
      @report = Report.new report_params
      @report.save
   end

   private

   def report_params
      params.require(:report).permit(progress_attributes: [:phase_id, :phase_lvl])
   end
end

这将使您能够定义以下内容:

#app/views/reports/new.html.erb
<%= form_for @report do |f| %>
   <%= f.fields_for :progress do |p| %>
      <%= p.collection_select :phase_id, @phases, :id, :name %>
      <%= p.number_field :phase_lvl %>
   <% end %>
   <%= f.submit %>
<% end %>

答案 1 :(得分:0)

听起来你可能想要的是多对多关系或has_and_belongs_to_many。为此,您需要在报告和流程之间创建一个具有report_id列和phase_id的联接表。有关更多信息,请查看此文档:http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

在模型中,您需要添加:

Class Report < ActiveRecord::Base

  has_and_belongs_to_many :phases

  ...
end

Class Phase < ActiveRecord::Base

  has_and_belongs_to_many :reports

  ...
end