【问题标题】:Rails has_many, :through - updating join table column when creating associated objectsRails has_many, :through - 创建关联对象时更新连接表列
【发布时间】:2013-07-07 14:38:43
【问题描述】:

我的问题

当创建清单时,如何为新清单的作业设置初始“job_position”(此 has_may 的 checklists_jobs 连接表中的列,:through 关联)?我最好的猜测是我应该使用回调(Checklists Controller 中的 after_filter?)。

我还需要将相同的方法应用于更新控制器操作,但我怀疑代码几乎相同。

用例

我正在以单一形式创建清单和相关的作业(任务)。在此表单中,用户可以创建新的清单(名称、描述)、创建新的工作(名称、描述)和/或从选择列表中选择现有的工作。

实际的表格在下面我的“代码”部分,但这里是用户在创建新清单时会看到的摘要:

  • 清单名称:
  • 清单说明(可选):

("Add a new job" 链接) - 如果点击链接,我使用 JS 将新的 Job (空白) 附加到表单:

  • 职位名称:
  • 职位描述(可选):

从职位库中添加职位:

  • (复选框)现有作业 1
  • (复选框)现有作业 2

创建检查表(按钮)

在我的联接表 (checklists_jobs) 上,我有必要的 checklist_id 和 job_id 字段,但我还有一个“job_position”字段,它告诉我该清单上作业的显示顺序。 (我将主要通过下面 Checklist.rb 代码中显示的“unarchived_jobs”关联来执行此操作。)

现在的工作方式

现在,我没有在创建清单时设置“job_position”字段,所以它只是空的。用户可以通过在 Checklists#Show 页面上对清单进行排序来手动设置“job_position”(在创建清单之后)。但是我想在创建清单时为加入记录设置 job_position 属性,以确保我保留/反映用户的实际定位当他们创建列表时(例如,他们添加的顺序使用“添加新工作”链接的新工作)。 注意:这是针对他们使用“添加新工作”链接添加的工作。从选择列表中选择的工作显然需要在创建清单后由用户手动排序。

我该怎么做?

代码

checklist.rb

class Checklist < ActiveRecord::Base
  scope :archived_state, lambda {|s| where(:archived => s) }

  has_many :checklists_jobs, :dependent => :destroy, :order => 'checklists_jobs.job_position'
  has_many :jobs, :through => :checklists_jobs
  has_many :unarchived_jobs, :through => :checklists_jobs, 
           :source => :job, 
           :conditions => ['checklists_jobs.archived = ?', false], :order => 'checklists_jobs.job_position'
end

job.rb

class Job < ActiveRecord::Base
  scope :archived_state, lambda {|s| where(:archived => s)}

  has_many :checklists_jobs, :dependent => :destroy
  has_many :checklists, :through => :checklists_jobs
end

checklists_job.rb

class ChecklistsJob < ActiveRecord::Base
  scope :archived_state, lambda {|s| where(:archived => s) }

  belongs_to :job
  belongs_to :checklist
  attr_accessible :job_position, :job_required
end

_form.html.erb(新清单表单)

<%= form_for @checklist, :html => { :class => 'form-inline' } do |f| %>
    <%= f.text_area :name, :rows => 1, :placeholder => 'Name the list...', :class => 'autoresizer checklist-name' %></br>
    <%= f.text_area :description, :rows => 1, :placeholder => 'Optional description...', :class => 'autoresizer' %>

    <%= f.fields_for :jobs, :html => { :class => 'form-inline' } do |j| %>
      <%= render "job_fields", :j => j  %>
    <% end %>

    <span class="add-new-job-link"><%= link_to_add_fields "add a new job", f, :jobs %></span>

    <% unless @job_list.empty? %>
    <legend>Add jobs from the Job Bank</legend>

    <% @job_list.each do |job| %>
      <div class="toggle">
        <label class="checkbox text-justify" for="<%=dom_id(job)%>">
          <%= check_box_tag "new_jobs[]", job.id, false, id: dom_id(job) %><strong><%= job.name %></strong> <small><%= job.description %></small>
        </label>
      </div>
    <% end %>

    <div class="form-actions">
      <%= f.submit nil, :class => 'btn btn-primary' %>
      <%= link_to 'Cancel', checklists_path, :class => 'btn' %>
    </div>
  <% end %>
<% end %>

【问题讨论】:

    标签: join ruby-on-rails-3.2 has-many-through


    【解决方案1】:

    感谢朋友的建议,我使用acts_as list gem 解决了这个问题。尽管我需要一些自定义调整,但实现起来很简单。默认 :column 是“位置”,所以我不得不覆盖它。我还需要一个自定义范围,因为我将它用于 has_many, :through 连接表,并且我在该表中“存档”了项目(我不想订购更新等)。

    以下是进行这些调整所需的代码行:

    checklists_job.rb

    acts_as_list :column => 'job_position', :scope => 'checklist_id = #{checklist_id} AND archived = false'
    

    这只是添加到我最初包含在我的问题中的代码中。

    #147 Sortable Lists (revised) 简要提到了acts_as_list。之所以简短提及,主要是因为它易于安装和使用。

    【讨论】:

    • 你是怎么解决这个问题的?我仍然不清楚您是如何将这项工作添加到连接表中的列
    • @MohamedElMahallawy 我使用了acts_as_list gem,并专门在连接表的模型(.rb 文件)中使用了它。我添加了“acts_as_list :column => 'job_position”... 行,以便“job_position”列跟踪位置。 act_as_list gem 本身负责“设置初始位置”。我认为诀窍是说出要用作位置的列的名称,因为它不是acts_as_list 所期望的标准“位置”。
    猜你喜欢
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 2013-04-22
    相关资源
    最近更新 更多