如何使用Rails中同一个表中的值对选择字段进行分类

时间:2014-07-24 16:46:58

标签: ruby-on-rails ruby

用户可以创建一个DeliveryCost,指定title,cost_per_unit和时间。除了来自常数的定时之外,所有字段都是唯一的。这是一个相关的片段

# Table name: delivery_costs
#
#  id            :integer          not null, primary key
#  title         :string(255)
#  cost_per_unit :float
#  created_at    :datetime
#  updated_at    :datetime
#  timing        :string(255)
#

class DeliveryCost < ActiveRecord::Base


  TIMING_INSTALL='Install'
  TIMING_BREAKDOWN='Breakdown'
  TIMING_TRANSPORT='Fuel'

  TIMINGS=[TIMING_INSTALL,TIMING_BREAKDOWN,TIMING_TRANSPORT]

  has_many :job_delivery_costs

然后将这些记录附加到JobDeliveryCost,可以输入更多字段。当用户从这些DeliveryCost标题中选择时,会为标题的每个实例显示时间......不是很漂亮

= f.input :delivery_cost_id, collection: DeliveryCost.order(:timing), :label_method => :timing, :value_method => :id, label: false
= f.input :delivery_cost_id, collection: DeliveryCost.order(:title), :label_method => :title, :value_method => :id, label: false

当然,我可以通过交付成本计时对交付成本标题进行分组,并将其应用于索引操作和下拉选择菜单操作。到目前为止我看过但看不到任何东西。我做了类似这样的事情来生成一个数组,

@delivery_cost = DeliveryCost.all
 @delivery_cost = @delivery_cost.map {|c| c.timing}.uniq! 

但是这只是创造一个新阵列而没什么价值......

我希望实现的一个小例子

 --install--
    foo
    bar
    foo
 --breakdown--
    blah
    cat
 --fuel--
    jimmy
    cricket

帮助!

# == Schema Information
#
# Table name: delivery_costs
#
#  id            :integer          not null, primary key
#  title         :string(255)
#  cost_per_unit :float
#  created_at    :datetime
#  updated_at    :datetime
#  timing        :string(255)
#

class DeliveryCost < ActiveRecord::Base

  TIMING_INSTALL='Install'
  TIMING_BREAKDOWN='Breakdown'
  TIMING_TRANSPORT='Fuel'
  TIMINGS=[TIMING_INSTALL,TIMING_BREAKDOWN,TIMING_TRANSPORT]

  before_destroy :survive_if_jobs

  has_many :job_delivery_costs
  has_many :jobs, through: :job_delivery_costs

  scope :install, -> { where(:timing => 'Install') }
  scope :breakdown, -> { where(:timing => 'Breakdown') }
  scope :fuel, -> { where(:timing => 'Fuel') }

  validates :timing, inclusion: TIMINGS
  validates :cost_per_unit, presence: true
  validates :title, presence: true

  def titles_by_timing
    self.pluck(:timing, :title).group_by(&:first).map { |k, v| [k, v.map(&:last)] }
  end

  private

  def survive_if_jobs
    jobs.empty?
  end

end

我从模型中得到意外的键盘结束错误,在他建议的数组采集方法中出现

错误消息

app / models / delivery_cost.rb:43:语法错误,意外的keyword_end,期待输入结束

Extracted source (around line #5):

@delivery_cost = DeliveryCost.all <this being line 5
 @delivery_cost = @delivery_cost.map {|c| c.timing}.uniq!
 # get_title
 raise

添加了视图部分

%td
                      = f.input :delivery_cost_id, collection: DeliveryCost.order(:timing), :label_method => :timing, :value_method => :id, label: false
                    %td
                      = f.select :title, grouped_options_for_select(DeliveryCost.titles_by_timing)
                    %td
                      = f.input :cost_per_unit, label: false
                    %td
                      = f.input :hour_count, label: false
                    %td
                      = f.input :quantity, label: false

谢谢!

1 个答案:

答案 0 :(得分:2)

您正在寻找的是grouped_options_for_select,它将嵌套数组或数组哈希作为输入。我将演示两者。

嵌套数组

DeliveryCost模型添加一个方法,该方法返回格式为的嵌套数组:

[["Install", ["foo", "bar"]], ["Breakdown", ["blah", "cat"]], ["Fuel", ["jimmy", "cricket"]]]

这是grouped_options_for_select允许的格式之一。获得此格式的一种方法是:

def self.titles_by_timing
  self.pluck(:timing, :title).group_by(&:first).map { |k, v| [k, v.map(&:last)] }
end

为了进一步解释上面的密集代码,我将逐个函数来完成它。 pluck(:timing, :title)将返回delivery_timing表格中每行的时间和标题。因此,使用您的示例,它将返回:

[["Install", "foo"], ["Install", "bar"], ["Breakdown", "blah"], ["Breakdown", "cat"], ["Fuel", "jimmy"], ["Fuel, "cricket"]]

然后,调用group_by(&:first)将生成嵌套数组的散列,其中键是时序,值是所有时序 - 标题组合。使用您的示例:

{ "Install" => [["Install", "foo"], ["Install", "bar"]], 
  "Breakdown" => [["Breakdown", "blah"], ["Breakdown", "cat"]], 
   "Fuel" => [["Fuel", "jimmy"], ["Fuel, "cricket"]] }

调用最后一部分map { |k, v| [k, v.map(&:last)] },将每个哈希键值对转换为包含两个元素的数组。第一个元素是timing,第二个元素是具有title的{​​{1}}数组。使用您的示例(请注意,这与顶部的格式相同):

timing

数组哈希

我相信使用数组散列更简单一些。格式如下:

[["Install", ["foo", "bar"]], ["Breakdown", ["blah", "cat"]], ["Fuel", ["jimmy", "cricket"]]]

同样,在{ "Install" => ["foo", "bar"], "Breakdown" => ["blah", "cat"], "Fuel" => ["jimmy", "cricket"] } 模型中添加方法以获取按时间分组的标题

DeliveryCost

前两个步骤(def self.titles_by_timing self.pluck(:timing, :title).group_by(&:first).each { |_, v| v.map!(&:last) } end pluck)与上面相同,但第三步采用嵌套数组的哈希值,即group_by,并使其成为哈希值数组,其中每个数组只是该时间的标题列表。与上面相同:

{ "Install" => [["Install", "foo"], ["Install, "bar"]], ...

在您的视图中

最后,在您看来,您可以使用{ "Install" => ["foo", "bar"], "Breakdown" => ["blah", "cat"], "Fuel" => ["jimmy", "cricket"] } 方法作为titles_by_timing来获取标题。这适用于嵌套数组数组哈希路由。

grouped_options_for_select