當然。像這樣的東西應該足夠了(假設例如「意大利麪條」被存儲在名爲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]
並得到相同的結果。完全可選,但非常方便。
不錯,謝謝!仍然讓我的頭腦圍繞着所有可以用Ruby和Rails做的很酷的小東西。 – Russell
很高興能幫到您,@Russell。 ActiveRecord指南(http://guides.rubyonrails.org/active_record_querying.html)是一個非常有用的指南,它不會在每週或每兩週閱讀完整內容。 ;)P.S.我注意到我在'scope:by_day'中省略了':'。你會想要介意的! –
'by_day_hash'應該返回'hsh',以便按預期工作。 – pgb