web-dev-qa-db-fra.com

Raccourci pour saisir deux attributs d'un objet ActiveRecord?

Existe-t-il un moyen plus court de procéder comme suit (

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

Userhas_many des employés. Les deux classes héritent de ActiveRecord::Base.

Deux choses que je n'aime pas dans ce qui précède

  1. Il charge les employés en mémoire avant le mappage,
  2. C'est verbeux (subjectif je suppose).

Y a-t-il une meilleure façon?

34
David Tuite

MISE À JOUR:

voir la solution de @ jamesharker: depuis ActiveRecord> = 4, pluck accepte plusieurs arguments:

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

RÉPONSE PRÉCÉDENTE:

pour une seule colonne en Rails> = 3.2, vous pouvez faire:

@user.employees.pluck(:name)

... mais comme vous devez saisir deux attributs, vous pouvez le faire:

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

si vous vraiment avez besoin d'une opération de niveau inférieur, regardez juste le source de #pluck , qui utilise select_all

46
m_x

Dans ActiveRecord> = 4 pluck accepte plusieurs arguments donc cet exemple deviendrait:

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

Si vous êtes coincé avec Rails 3 vous pouvez ajouter this.pluck_all extension: http://meltingice.net/2013/06/11/pluck-multiple-columns-Rails/

7
NNA

En termes de création d'une méthode Rails 3 qui se comporte de la même manière que la Rails 4 pluck avec plusieurs colonnes. Cela génère un tableau similaire (plutôt qu'une clé hachée) Cela devrait vous éviter un peu de peine si vous venez de mettre à niveau et que vous souhaitez nettoyer le code.

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

Debout sur les épaules de géants et de tous

0
Carpela

Une autre option consiste à:

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

Je peux imaginer que vous préférez avoir des clés symbolisées. Si tel est le cas, utilisez le #symbolize_keys méthode.

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

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

0
3limin4t0r

Ajoutez ce patch de singe qui fournit la fonctionnalité de saisie de plusieurs colonnes dans 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

Renommez la méthode de pluck en pluck_all si vous ne souhaitez pas remplacer la fonctionnalité d'origine pluck

0
Weston Ganger

Le pluck_all la méthode a bien fonctionné jusqu'à ce que je passe de Rails 3.2 à Rails 4.

Voici un joyau pluck_all pour résoudre ce problème, ce qui rend pluck_all prise en charge de la méthode non seulement dans Rails 3 mais dans Rails 4 et Rails 5. J'espère que cela aidera ceux qui vont mettre à niveau Rails version.

0
khiav reoy