Misha Moroshko
Misha Moroshko

Reputation: 171399

Rails 3: How to create a named scope based on Controller's method?

In my ApplicationController I have the demo_mode? method (which returns true when the currently logged in user type is "demo").

Post model has the publisher_id field, which refers to Users table.

User has the user_type field, one of the possible values of which is "demo".

Bottom line: post p was published by a "demo" user if and only if:

User.find(p.publisher_id).user_type == "demo"

I would like to create a named scope Post.relevant that will return:

How would you create such a named scope ? Should I move demo_mode? to other place ?

Upvotes: 2

Views: 2015

Answers (3)

DGM
DGM

Reputation: 26979

Use a lambda to make a dynamic scope, and keep the session info out of the model:

In your model:

class Post < ActiveRecord::Base
  scope :relevant, lambda {|demo_mode|
     joins(:publisher).
     where("publishers.user_type #{demo_mode ? '' : 'NOT'} LIKE 'demo'")
  }
end

And then in the controller:

posts = Post.relevant(demo_mode?)

Upvotes: 2

moritz
moritz

Reputation: 25767

If I understand correctly, the demo state is determined by the session so only the controller knows about it. On the other hand, the controller (or possibly the view) is the only place where you would want to query the scope. If all of this is correct, I would add a method to ApplicationController like this:

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

Technically, this is not a named scope. Rails 3, however does not make much of a difference between named scopes and the standard query interface.

Upvotes: 0

VMOrtega
VMOrtega

Reputation: 1978

Try something like this

class Post < ActiveRecord::Base

    scope :relevant, joins("INNER JOIN users ON (users.user_type = 'demo')").where("publisher_id = users.id")

end

Upvotes: 0

Related Questions