2013-09-08 1 views
1

Я работаю над приложением Rails с MySQL.
У меня есть таблицы, как это:Rails ActiveRecord, выбирая отдельные поля из объединенной таблицы и возвращая все модели

gifts 
id, basket_id, orange_id, berry_id 

berries 
id, action_id, name 

Это их модель:

class Gift < ActiveRecord::Base 
    belongs_to :basket 
    belongs_to :orange 
    belongs_to :berry 
    ... 
end 

class Berry < ActiveRecord::Base 
    belongs_to :action 
    has_one :gift 
    ... 
end 

class Basket < ActiveRecord::Base 
    has_many :gifts 
    ... 
end 

В корзине модели, у меня есть gifts переменного, которая содержит все подарки для этой корзины, через ассоциацию I определенная в модели корзины - в основном "SELECT * FROM gifts WHERE basket_id = ?", self.id

Я хочу сгруппировать все уникальные berry actions для каждого апельсина.
Текущий подход:

def get_data 
    data = {} 
    gifts.each |gift| do 
    orange_id = gift.orange_id 
    data[orange_id] ||= { :basket_id => gift.basket_id, :name => gift.orange.name, :actions => Set.new } 
    data[orange_id] << { :action_name => gift.berry.action.name } 
    end 
return data 

Мой подход был перебрать gifts и сохранить уникальный berry actions в набор для каждого уникального orange_id, однако такой подход является медленным, если у меня есть тысячи подарков с несколькими berry actions для каждой ягоды. Если есть 2000 подарков и 4 действия, я зацикливаю 8000 раз.

Подарки могут иметь одинаковые апельсины и корзины, но всегда разные ягоды.

Я хочу выполнить этот запрос вместо этого, который будет быстрее, поскольку я буду выполнять итерацию через уникальные апельсины вместо всех подарков (для каждой корзины есть только пара сотен апельсинов).

SELECT DISTINCT g.basket_id, g.orange_id, g.berry_id, b.action_id 
FROM gifts AS g 
JOIN berries AS b 
ON g.berry_id = b.id 

Может ли кто-нибудь показать мне, как это сделать, используя методы Rails ActiveRecord? Я хотел бы иметь возможность выполнять итерацию по каждой строке этого запроса и выполнять действия в выбранных полях. Было бы также здорово, если бы можно было вернуть соответствующие модели, чтобы я мог захватить модели basket, orange, berry и action для каждой строки.

ответ

1

Попробуйте следующее:

gifts = Gift.joins(:berry).select(:basket_id, :orange_id, :berry_id, :action_id).uniq.to_a 

gifts проведет множество подарков только с атрибутами, указанными в select initializated:

puts gifts.first.attributes 
+0

совершенны, спасибо! –