2010-08-08 5 views
2

У меня есть модели club и course, где курс принадлежит клубу, а в клубе много курсов.Рельсы: Условная загрузка ассоциаций

Когда я загружаю клуб, я также хочу загрузить связанные с ним курсы, но я хочу только загрузить те, которые соответствуют условному тесту (approved? == true).

Это просто, как это сделать, если бы я работал непосредственно с курсами:

@courses = Course.find(:all, :conditions => {:approved => true }) 

Но я хотел бы сделать это как часть заявления:

@club = Club.find(params[:id]) 

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

Спасибо!

ответ

0

Окончательное решение было получено из сочетания ответов, но не совсем дошло до конца.

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

Так course модель выглядит как это:

class Course < ActiveRecord::Base 
    belongs_to :club 

    named_scope :have_approval, :conditions => { :approved => true } 
    named_scope :need_approval, :conditions => { :approved => false } 
end 

и собрать все одобренные курсы это так же просто, как:

@approved_courses = Course.have_approval 

Или при работе с club, получая утвержденный курсы в клубе так же просто:

@club = Club.find(:first) 
@approved_courses_in_club = @club.courses.have_approval 

Named сфера - это человек!

+1

вы можете использовать динамическую область вместо named_scope i.e. '@ club.courses.scoped_by_approval (true)' OR '@ club.courses.scoped_by_approval (false)'. –

+0

Эй, это просто отлично! – Jay

2

Если рассматривать только курс клубную, если он был одобрен, вы можете сделать

class Club < ActiveRecord::Base 
    has_many :courses, :conditions => {:approved => true} 
end 

и в контроллере

@club = Club.find(params[:id], :include => :courses) 

Теперь, я не знаю, если я неправильно понял, но вы сказали: «Ваши взгляды построены таким образом». Вы имеете в виду ваши контроллеры? Потому что, если у вас есть такая логика в ваших взглядах ... DHH убивает котенка каждый раз, когда кто-то это делает.

+0

Бедные котята, но нет. Я боялся загружать как переменную '@ club', так и' @ courses', что означало бы избавление от всех ссылок @ @ club.courses в моих взглядах. У меня есть пространство имен admin, где я хотел бы загрузить неутвержденные курсы (как если бы это не было в модели), как бы я это сделал с помощью вашего решения? – Jay

1

Вы можете использовать default_scope для этого:

class Club < ActiveRecord::Base 
    has_many :courses, conditions => {:approved => true} 
    default_scope :include => :courses 
end 

class Course < ActiveRecord::Base 
    default_scope :conditions => {:approved => true} 
end 

Теперь вы можете сделать это:

@club = Club.find(1) # this will eager load approved courses. 

Ссылка:

Article о default_scope.

Примечание 1

Я изменил courses Assocation в Club классе, чтобы выбрать одобренные курсы. Теоретически это не требуется, поскольку класс Course имеет область по умолчанию. Но похоже, что по умолчанию для запросов с нетерпением загружено задание по умолчанию.

Примечание 2

лично я не горю нагрузки на Course объекты через default_scope. Выполнение этого с помощью default_scope дает вам ненавязчивое решение по вашему желанию.

Я бы добавил пункт include на адрес find, чтобы зарядить объекты Course только тогда, когда это необходимо.

Примечание 3

@Ryan Бигг:

Райан Бейтс говорит о стандартных прицелах на полпути через этот его screen cast. Он дает пример использования областей по умолчанию, чтобы исключить удаленные записи, т.е.

default_scope :conditions => "delete_at IS NULL" 

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

Club.with_exclusive_scope{find(1)} 
+0

Я бы не использовал: условия ** когда-либо ** в 'default_scope': как Rails различает условия' default_scope' и другую группу условий, которые вы указали? Вместо этого я бы использовал 'named_scope' для этого и вместо этого назову это. Решение @Chubas тоже хорошо. –

+0

Я не согласен, фильтрация 'deleted' и' approved' records - подходящее использование для default_scope. В этом случае каждая операция 'find' на модели' Course' требует фильтрации неутвержденных курсов. В случаях, когда пользователю необходимо включить несанкционированные записи, он может использовать 'with_exclusive_scope'. –

+0

Пользователь говорит: 'потому что мои представления построены таким образом, и я бы предпочел не менять их. ', Это решение позволяет пользователю реализовать функциональность ненавязчиво. –

Смежные вопросы