44

次のことを行うためのより短い方法はありますか(

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

User has_many従業員。どちらのクラスもから継承しActiveRecord::Baseます。

上記について私が気に入らない2つのこと

  1. マッピングする前に従業員をメモリにロードします。
  2. それは冗長です(主観的だと思います)。

もっと良い方法はありますか?

4

7 に答える 7

59

アップデート:

@jamesharker の解決策を参照してください: ActiveRecord >= 4 から、pluck複数の引数を受け入れます:

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

前の回答:

レール>= 3.2の単一の列の場合、次のことができます:

@user.employees.pluck(:name)

...しかし、2 つの属性を取得する必要があるため、次のことができます。

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

低レベルの操作が本当に必要な場合は、#pluck のソースを見てください。select_all

于 2012-12-08T11:47:23.917 に答える
42

ActiveRecord >= 4 では、 pluckは複数の引数を受け入れるため、この例は次のようになります。

@user.employees.pluck(:id, :name)
于 2013-11-21T13:23:12.127 に答える
8

Rails 3 に行き詰まっている場合は、次の拡張機能を追加できます .pluck_all: http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/

于 2014-07-30T10:09:49.687 に答える
0

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

元の機能をオーバーライドしたくない場合は、メソッドの名前を からpluckに変更しますpluck_allpluck

于 2016-05-13T03:58:58.377 に答える