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
Другие вопросы по тегам