Rails и ActiveRecord отлично справляются с тем, что я считаю чрезвычайно простыми запросами, имеющими дело с одной моделью. Теперь у меня есть ситуация, когда мне нужно сделать что-то немного более сложное, но все же тривиальное, и я не знаю, как это сделать.
У меня есть User
, что has_many :images
. Каждый Image has_many :thumbnails
.
На моей индексной странице /images
я хочу отобразить миниатюру small для каждого изображения, которое принадлежит зарегистрированному пользователю. Простой запрос, но поскольку для этого требуются условия для нескольких таблиц, я не уверен, как подходить к нему по-настоящему в стиле Rails. Я бы предпочел избегать написания SQL и справляться с вытекающими отсюда головными болями.
Я вижу, что рельсы предлагают опцию :joins
, но это кажется довольно не элегантным задним числом. Это лучший способ удовлетворить такое требование или есть лучший способ, которого я просто не нашел?
Спасибо.
ОБНОВЛЕНИЕ: Мне сказали об именованных областях, и я должен признать, что сейчас испытываю к ним очень неуместные чувства. Это позволяет применять довольно сложные условия очень элегантно с большим количеством синтаксического сахара. Например, я могу создать именованную область в моей модели изображений для изображений, принадлежащих данному пользователю, и сделать ее динамической:
class Image < ActiveRecord::Base
named_scope :owned_by,
lambda {
|user_id| {
:conditions => { :user_id => user_id }
}
}
end
Я также могу применить именованную область на моей модели миниатюр, чтобы указать маленькую миниатюру:
class Thumbnail < ActiveRecord::Base
named_scope :small, :conditions => { :name => 'Small' }
end
Теперь я могу связать их вместе, чтобы сделать довольно мощные вещи, которые читаются красиво. В моем контроллере я могу вернуть все изображения для данного пользователя:
@images = Image.owned_by( current_user )
Однако, на мой взгляд, я хочу отобразить маленькую миниатюру, так что мы сильно цепляемся:
<% for image in @images %>
<tr>
<td><%= h( image.name ) %></td>
<td><%= link_to( image_tag( image.thumbnails.small.first.binary.uri, :alt => h( image.name ), :title => h( image.description ) ), :action => :show, :id => image.id ) %></td>
</tr>
<% end %>
Проверьте image_tag
. Для каждого изображения он идентифицирует первую маленькую миниатюру, а затем связывает ее, чтобы получить физическое местоположение файла. Это не совсем то, что я искал, так как для каждого изображения требуется дополнительное попадание в базу данных, но, возможно, это более точно соответствует моим потребностям в данном конкретном случае.