0

我的问题

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

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

用例

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

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

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

(“添加新工作”链接) - 如果单击链接,我使用 JS 将新工作(空白)附加到表单:

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

从工作银行添加工作:

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

创建清单(按钮)

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

它现在是如何工作的

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

我该怎么做呢?

代码

清单.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

工作.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 %>
4

1 回答 1

0

感谢朋友的建议,我使用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 可排序列表(修订版)简要提及acts_as_list。提及很简短,主要是因为安装和使用非常容易。

于 2013-07-11T01:18:00.700 回答