繁体   English   中英

从ActiveRecord对象中提取两个属性的快捷方式?

[英]Shortcut for plucking two attributes from an ActiveRecord object?

有没有更短的方法来执行以下操作(

@user.employees.map { |e| { id: e.id, name: e.name } }
# => [{ id: 1, name: 'Pete' }, { id: 2, name: 'Fred' }]

User has_many员工。 这两个类都继承自ActiveRecord::Base

我不喜欢以上两件事

  1. 它将员工在映射之前加载到内存中,
  2. 它很冗长(我猜是主观的)。

有没有更好的办法?

更新:

见@ jamesharker的解决方案:从ActiveRecord的> = 4, pluck接受多个参数:

@user.employees.pluck(:id, :name)

上一个答案:

对于rails> = 3.2中的单个列,可以执行以下操作:

@user.employees.pluck(:name)

...但是您必须选择两个属性,因此可以执行以下操作:

@user.employees.select([:id, :name]).map {|e| {id: e.id, name: e.name} } 
# or map &:attributes, maybe

如果您确实需要较低级别的操作,只需查看使用select_all 的#pluck

在ActiveRecord> = 4中, pluck接受多个参数,因此该示例将变为:

@user.employees.pluck(:id, :name)

如果你被卡住了Rails 3,您可以添加这个 .pluck_all扩展: http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/

添加此猴子补丁,该补丁在Rails 3中提供多列抽取功能。

# config/initializers/pluck_all.rb

if Rails.version[0] == '3'
  ActiveRecord::Relation.class_eval do
    def pluck(*args)
      args.map! do |column_name|
        if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
          "#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
        else
          column_name.to_s
        end
      end

      relation = clone
      relation.select_values = args
      klass.connection.select_all(relation.arel).map! do |attributes|
        initialized_attributes = klass.initialize_attributes(attributes)
        attributes.map do |key, attr|
          klass.type_cast_attribute(key, initialized_attributes)
        end
      end
    end
  end
end

重命名从方法pluckpluck_all如果你不想覆盖原来的pluck功能

就制作Rails 3方法而言,其行为与采用多列的Rails 4采摘方法相同。 这将输出类似的数组(而不是哈希键值集合)。 如果您要升级并想要清理代码,这应该会减轻一些麻烦。

module ActiveRecord
  class Relation
    def pluck_all(*args)
      args.map! do |column_name|
        if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
          "#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
        else
          column_name.to_s
        end
      end

      relation = clone
      relation.select_values = args
      klass.connection.select_all(relation.arel).map! do |attributes|
        initialized_attributes = klass.initialize_attributes(attributes)
        attributes.map do |key, attribute|
          klass.type_cast_attribute(key, initialized_attributes)
        end
      end
    end
  end
end

站在巨人和所有人的肩膀上

在我要从Rails 3.2升级到Rails 4之前, pluck_all方法效果很好。

这是一个可解决此问题的宝石pluck_all ,不仅在Rails 3中而且在Rails 4和Rails 5中都支持pluck_all方法。希望这对将要升级Rails版本的人有所帮助。

另一种选择是:

@user.employees.select(:id, :name).as_json
#=> [{"id" => 1, "name" => "Pete"}, {"id" => 2, "name" => "Fred"}]

我可以想象您宁愿使用符号键。 如果是这种情况,请使用#symbolize_keys方法。

@user.employees.select(:id, :name).as_json.map(&:symbolize_keys)
#=> [{id: 1, name: "Pete"}, {id: 2, name: "Fred"}]

请参阅: http : //api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM