Конечно.Что-то вроде этого должно быть достаточно (при условии, что, например, «спагетти» хранится в столбце с именем food
).
class Dish
belongs_to :menu
scope :by_day { select [ :day, :food ] }
def self.by_day_hash
by_day.all.reduce({}) {|hsh,dish| hsh[dish.day] = dish.food; hsh }
end
end
class Menu
has_many :dishes
def dishes_by_day
dishes.by_day_hash
end
end
# Usage
m = Menu.where( ... )
m.dishes_by_day #=> { "monday" => "Spaghetti", "tuesday" => "Tofu" }
Так что здесь происходит то, что в Dish
область действия by_day
возвращает только два столбца, day
и food
.Однако он по-прежнему возвращает Dish
объектов, а не хэш (потому что это то, что делают области), поэтому мы определяем метод класса by_day_hash
, который принимает этот результат и превращает его в хэш.
Затемв Menu
мы определяем dishes_by_day
, который просто вызывает метод, который мы сделали выше для ассоциации.Вы могли бы просто назвать это dishes
, но я думаю, что лучше сохранить это имя для исходной ассоциации, поскольку вы, возможно, захотите использовать его позже для других вещей.
Между прочим ( необязательно вещи ниже, пропустите сейчас, если ваши глаза застеклены) , я мог бы вместо этого определить by_day_hash
:
class Dish
belongs_to :menu
scope :by_day { select [ :day, :hash ] }
def to_s
food
end
def by_day_hash
hsh = HashWithIndifferentAccess.new
by_day.reduce(hsh) {|hsh, dish| hsh[dish.day] = dish }
end
end
# Usage
m = Menu.where( ... )
m.dishes_by_day #=> { "monday" => #<Dish food: "Spaghetti", ...>, "tuesday" => #<Dish food: "Tofu", ...>, ... }
... Таким образом, вы по-прежнему получаете полный Dish
объект, когда вы вызываете, например, by_day_hash["monday"]
, но метод to_s
означает, что вы можете просто перетащить его в представление типа <%= @menu.dishes_by_day["monday"] %>
и получить «Спагетти» вместо #<Dish day: "monday", food: "Spaghetti">
.
Наконец, вы также можетеобратите внимание, я использовал HashWithIndifferentAccess.new
вместо {}
(хэш).HashWithIndifferentAccess - это класс, предоставляемый (и используемый везде) Rails, который идентичен Hash, но позволяет вам делать, например, some_hash["monday"]
или some_hash[:monday]
и получать тот же результат.Абсолютно необязательно, но очень удобно.