Rails 3: Как создать именованную область видимости на основе метода контроллера?
В моем ApplicationController
у меня есть demo_mode?
метод (который возвращает true
когда в данный момент вошедшим в систему типом пользователя является "демо").
Post
модель имеет publisher_id
поле, которое относится к Users
Таблица.
User
имеет user_type
поле, одним из возможных значений которого является "демо".
Итог: пост p
был опубликован пользователем "demo" в том и только в том случае, если:
User.find(p.publisher_id).user_type == "demo"
Я хотел бы создать именованную область Post.relevant
что вернется:
- все сообщения, которые были опубликованы пользователями "демо", если
demo_mode? == true
- все сообщения, которые были опубликованы не "демо" пользователями, если
demo_mode? == false
Как бы вы создали такую именованную область? Должен ли я двигаться demo_mode?
в другое место?
3 ответа
Используйте лямбду, чтобы создать динамическую область видимости, и сохраните информацию о сеансе вне модели:
В вашей модели:
class Post < ActiveRecord::Base
scope :relevant, lambda {|demo_mode|
joins(:publisher).
where("publishers.user_type #{demo_mode ? '' : 'NOT'} LIKE 'demo'")
}
end
И тогда в контроллере:
posts = Post.relevant(demo_mode?)
Если я правильно понимаю, демонстрационное состояние определяется сессией, так что об этом знает только контроллер. С другой стороны, контроллер (или, возможно, представление) является единственным местом, где вы хотите запросить область. Если все это правильно, я бы добавил метод в ApplicationController следующим образом:
class ApplicationController < ActionController::Base
def relevant_posts
Post.joins(:publisher).
where("publishers.user_type #{demo_mode? ? '' : 'NOT'} LIKE 'demo'")
end
...
helper_method :relevant_posts # if you want it to be available in views
end
Технически это не именованная область. Rails 3, однако, не имеет большого значения для именованных областей и стандартного интерфейса запросов.
Попробуйте что-то вроде этого
class Post < ActiveRecord::Base
scope :relevant, joins("INNER JOIN users ON (users.user_type = 'demo')").where("publisher_id = users.id")
end