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
Shortcut for plucking two attributes from an ActiveRecord object?
提问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
以上两点我不喜欢
- It loads employees into memory before mapping,
- It's verbose (subjective I guess).
- 它在映射之前将员工加载到内存中,
- 它很冗长(我猜是主观的)。
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
回答by jamesharker
回答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
如果您不想覆盖原始功能pluck,pluck_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

