开发者

Setting a Session Variable in a Model

With Rails 3, How can you set a session va开发者_运维知识库riable in a model

session[:cannot_reason] = "no such item"

I'd like to set the above in my user model. Right now I get this error:

undefined local variable or method `session' for #<User:0x00000102eb9c38>

Ideas? Thanks


There's some unnecessary cargo-culting regarding whether or not models should have access to session data. I think this is silly, since session is really just another form of persistant storage (albeit for a much shorter time frame) and, in Rails, it seems ok to have your domain object also be able to persist itself.

That being said, the not very clean way to do it would be to pass the session hash as a parameter into the User method that will operate on it:

class User < ...
  def mymethod(session, count)
    session[:count] = count
  end
end

In your controller, you would then do something like:

def update
  # ...
  user.mymethod(session, count)
end

Imagining that mymethod is implementing some business logic, this will modify the session hash appropriately. You don't have to pass the session hash back out to the controller because Ruby passes around references to objects (like a Hash)--modifications are made destructively to those referenced objects.

A word of advice: The above example, in my opinion, is smelly. This is because User is an ActiveRecord model which (I'm assuming) persists to a database and we're adding behavior that makes it also persist to a session cookie. To me, this violates SRP and should be avoided.

The way I would implement this would be to extract the session storage logic out to a separate domain object that encapsulates the reason for its existence. Maybe, for example, count isn't just a "count", it's the total of the number of items in the user's temporary cart.

class TemporaryCart
  def initialize(session)
    @session = session
  end

  def add_item
    # ... other item adding logic
    @session[:temporary_cart][:num_items] += 1
  end
end

Now your controller would look like this:

def update
  # ...
  TemporaryCart.new(session).add_item
end

This is much more revealing and opens the door for an obvious way to abstract out session access code if you find yourself using session storage a lot. Also notice that I namespaced the data in the session hash (but didn't show this implementation). I recommend you do this so you don't step on your own toes when adding other data.


In short, you can't. By design, models don't have access to cookies and the session. If you to access items in the session from your model, you'll need to explicitly pass them in from the controller.


The session object is not visible in models. Either pass it as a parameter to a method in your model (IMHO bad) or define a method in your model which returns what you want and then store it in the session (from your controller).

class User < ...
  def item_status
    return :no_such_item
  end
end

In your controller

session[:item_status] = current_user.item_status
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜