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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13777086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:09:19  来源:igfitidea点击:

Shortcut for plucking two attributes from an ActiveRecord object?

ruby-on-railsrubyruby-on-rails-3

提问by David Tuite

Is there a shorter way to do the following (

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

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

Userhas_manyemployees. Both classes inherit from ActiveRecord::Base.

Userhas_many雇员。这两个类都继承自ActiveRecord::Base.

Two things I don't like about the above

以上两点我不喜欢

  1. It loads employees into memory before mapping,
  2. It's verbose (subjective I guess).
  1. 它在映射之前将员工加载到内存中,
  2. 它很冗长(我猜是主观的)。

Is there a better way?

有没有更好的办法?

回答by m_x

UPDATE:

更新:

see @jamesharker's solution: from ActiveRecord >= 4, pluckaccepts multiple arguments:

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

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

PREVIOUS ANSWER:

以前的答案:

for a single column in rails >= 3.2, you can do :

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

@user.employees.pluck(:name)

... but as you have to pluck two attributes, you can do :

...但由于您必须选择两个属性,您可以这样做:

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

if you reallyneed lower-level operation, just look at the source of #pluck, that uses select_all

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

回答by jamesharker

In ActiveRecord >= 4 pluckaccepts multiple arguments so this example would become:

在 ActiveRecord >= 4 pluck接受多个参数,所以这个例子将变成:

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

回答by NNA

If you are stuck with Rails 3 you can add this.pluck_allextension : http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/

如果你坚持使用 Rails 3,你可以添加这个.pluck_all扩展:http: //meltingice.net/2013/06/11/pluck-multiple-columns-rails/

回答by Weston Ganger

Add this monkey patch which provides the multi columns pluck functionality in Rails 3.

添加这个猴子补丁,它提供了 Rails 3 中的多列 pluck 功能。

# 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

Rename the method from pluckto pluck_allif you dont want to override the original pluckfunctionality

如果您不想覆盖原始功能pluckpluck_all请将方法重命名为pluck

回答by Carpela

In terms of making a rails 3 method that behaves the same as the Rails 4 pluck with multiple columns. This outputs a similar array (rather than a hashed key value collection). This should save a bit of pain if you ever come to upgrade and want to clean up the code.

在制作 Rails 3 方法方面,其行为与具有多个列的 Rails 4 pluck 相同。这会输出一个类似的数组(而不是散列的键值集合)。如果您要升级并想要清理代码,这应该会省去一些麻烦。

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

Standing on the shoulders of giants and all

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

回答by khiav reoy

The pluck_allmethod worked well until I'm going to upgrade from Rails 3.2 to Rails 4.

pluck_all方法运行良好,直到我要从 Rails 3.2 升级到 Rails 4。

Here is a gem pluck_allto solve this, making pluck_allmethod support not only in Rails 3 but in Rails 4 and Rails 5. Hope this will help those who are going to upgrade rails version.

这里有一个 gem pluck_all来解决这个问题,pluck_all不仅在 Rails 3 中,而且在 Rails 4 和 Rails 5 中都支持方法。希望这对那些将要升级 rails 版本的人有所帮助。

回答by 3limin4t0r

Another option is to:

另一种选择是:

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

I can imagine that you'd rather have symbolized keys. If that's the case use the #symbolize_keysmethod.

我可以想象你更喜欢符号键。如果是这种情况,请使用该#symbolize_keys方法。

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

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

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