2017-10-11 5 views
1

J'ai un modèle ActiveRecord comme ceci:Comment cueillir plusieurs attributs dans Rails 3.x?

class Person < ActiveRecord::Base 
    attr_accessible :name 
end 

et besoin d'obtenir un mappage de hachage Person « s id s à leurs name s:

{1 => "Paul", 2 => "Aliyah", 3 => ... } 

Maintenant, la manière évidente serait

Person.all.collect { |p| [p.id, p.name] }.to_h 

Cependant, je n'ai pas besoin d'instancier tous les Person, j'ai juste besoin le hachage. Dans Rails 4, je peux .pluck(:id, :name) au lieu de collect, mais dans 3.x, pluck prend seulement un argument. Cependant, je trouve cette solution de contournement pour obtenir ce que je veux sans charger les modèles:

Person.all.group(:id).minimum(:name) 

Question: vais-je brûler en enfer? Aussi, y a-t-il une façon plus élégante de faire cela, et y a-t-il des inconvénients de cette approche hacky dont je ne suis peut-être pas au courant? Merci!

Répondre

3

Voici une assez bonne rédiger de cette situation et diverses tactiques pour manipuler: Plucking Multiple Columns in Rails 3

Ma préférence des solutions proposées, il est de faire et d'inclure un module:

# multi_pluck.rb 
require 'active_support/concern' 

module MultiPluck 
    extend ActiveSupport::Concern 

    included do 
    def self.pluck_all(relation, *args) 
     connection.select_all(relation.select(args)) 
    end 
    end 
end 
0

Pour éviter de charger tous les objets que vous pouvez faire:

hash = Hash.new 
ActiveRecord::Base.connection.execute("SELECT id, name FROM persons").each {|person| hash[person['id'].to_s] = person['name'].to_s} 
1
class Person < ActiveRecord::Base 
    attr_accessible :name 

    def self.pluck_id_and_name 
    result = connection.select_all(select(:id, :name)) 
    if result.any? 
     # if you are using Ruby 2.1+ 
     result.to_h 
     # Works in 1.9.3+ 
     Hash[result] 
    end 
    end 
end 

Étant donné que le résultat devrait être un tableau de tableaux, nous pouvons utiliser bonne astuce pour obtenir un hachage avec le premier élément en tant que touches et la seconde en tant que valeurs:

Hash[ [ [1, "Joe"], [2, "Jill"] ] ] 
# => { 1 => "Joe", 2 => "Jill"} 

Voir: