Ruby-on-rails 在模型中设置会话变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7216847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:52:15  来源:igfitidea点击:

Setting a Session Variable in a Model

ruby-on-railsruby-on-rails-3

提问by AnApprentice

With Rails 3, How can you set a session variable in a model

使用 Rails 3,如何在模型中设置会话变量

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

想法?谢谢

回答by andrewle

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.

关于模型是否应该访问会话数据,有一些不必要的货物崇拜。我认为这很愚蠢,因为 session 实际上只是另一种形式的持久性存储(尽管时间范围要短得多),而且在 Rails 中,让域对象也能够自身持久化似乎没问题。

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:

话虽如此,但不是很干净的方法是将会话哈希作为参数传递给将对其进行操作的 User 方法:

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 mymethodis implementing some business logic, this will modify the sessionhash appropriately. You don't have to pass the sessionhash back out to the controller because Ruby passes around references to objects (like a Hash)--modifications are made destructively to those referenced objects.

想象一下mymethod正在实现一些业务逻辑,这将session适当地修改散列。您不必将session散列传回控制器,因为 Ruby 会传递对对象的引用(如散列)——对那些被引用的对象进行破坏性修改。

A word of advice: The above example, in my opinion, is smelly. This is because Useris 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.

忠告:上面的例子,在我看来,是臭的。这是因为User是一个 ActiveRecord 模型,它(我假设)持久化到数据库,并且我们正在添加使其也持久化到会话 cookie 的行为。对我来说,这违反了 SRP,应该避免。

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, countisn't just a "count", it's the total of the number of items in the user's temporary cart.

我实现这一点的方法是将会话存储逻辑提取到一个单独的域对象中,该域对象封装了其存在的原因。例如,也许count不仅仅是“计数”,而是用户临时购物车中商品的总数。

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.

如果您发现自己经常使用会话存储,这将更具启发性,并为一种抽象会话访问代码的明显方法打开了大门。还要注意,我在会话哈希中命名了数据(但没有显示这个实现)。我建议您这样做,以免在添加其他数据时踩到自己的脚趾。

回答by Michael Fairley

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.

简而言之,你不能。按照设计,模型无权访问 cookie 和会话。如果您从模型访问会话中的项目,则需要从控制器显式传递它们。

回答by Matt

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