在Rails中访问另一个控制器中的一个控制器变量

我有一个C编程背景,我正在学习侧面项目的Ruby / Rails。 目前,我正在努力了解变量的范围是如何工作的。 这是我遇到的问题的一个例子。 我有一个用户和一个产品型号。 在Product DB中,我存储不同的产品,其中一个字段是userid字段,该字段与存储在User表中的用户ID相匹配。 在用户登录后 – 我显示用户的姓名,电子邮件等(这存储在@current_user中),然后有一个链接显示用户拥有的不同产品。 我通过users / show.html.erb中的以下代码执行此操作,如下所示:…

名称:

到现在为止还挺好。 当我单击“产品”链接时,它会将我带到products / index.html.erb并执行以下代码(我想过滤此显示以仅显示@ current_user.userid拥有的产品。我该怎么做?下面的代码给了我一个运行时错误,因为@current_user评估为nil我相信。如果我删除了“if”子句,那么所有产品都显示出来并不是我想要的。会感激任何提示。

      

谢谢,

我打算对此作出评论,但我认为这是值得回答的。 不仅仅是rails,而是整个互联网,要理解的是HTTP是无状态的 。 这意味着在您的控制器中,您可以获取用户的信息,使用数据库中的所有内容构建一个网页,然后将其发送给他们。 然后他们在页面上执行某些操作并发送请求以获取另一页或更多数据,并且您的rails应用程序就像“哦,你好!你是谁?” 因为所有那些填充了很好信息的变量都已消失了。 每次你的应用程序收到请求时,它都会创建一个正在使用的控制器的全新实例,然后随后将其删除,以及其中的所有内容。 这一点非常重要,因为目前可能会有数千或数百万人登录您的终极飞盘联盟网站,试图找出周六谁在哪里比赛。 并且您希望向正确的人提供正确的信息,您不能认为您上次发送信息的人是现在要求您提供新信息的人。

因此,我们需要使用session ,每次发送页面时传递给客户端浏览器的一些信息,浏览器会在每次请求时将其发送给您。 您在会话中放置了足够的信息,以便在收到响应时可以使用它来重建服务器所需的内容。 我将使这个变得非常简单,然后向您推荐Rails安全指南 ,您可以在其中获取更重要的信息。 实际上,我只会使用他们的例子:

您可以通过以下方式将用户ID添加到会话中:

 session[:user_id] = @current_user.id 

然后以这种方式取回它:

 @current_user = User.find(session[:user_id]) 

然后使用您的用户模型(在本例中)从数据库中获取所需的特定信息。 这是Rails指南的另一个链接,因为它非常好,我将它链接两次: http : //guides.rubyonrails.org/security.html#what-are-sessions-questionmark

如果你正在做一些需要密码的东西,你可以使用类似devise的gem, 这里的说明 ,但要注意,它完全劫持你的用户模型,你的会话控制器,一些视图,基本上所有与登录和身份相关的事情。 它不容易定制,但它使所有这些东西和事情变得更加复杂,实现起来非常简单。 如果您不需要任何用户名或密码而且您正在做一些非常简单的事情,请跳过特殊的gem并自己使用会话。

您必须在每个请求上初始化@current_user ,而不仅仅是在用户登录之后。控制器实例变量不会在请求之间保持不变。

以下是执行此操作的常用方法:

  1. 将用户ID存储在会话中。
  2. ApplicationController中创建一个“before”filter,用于从会话中检索用户ID并初始化实例变量。

在一个操作中设置的实例变量无法在另一个操作中访问。 如前所述,您需要将user_id存储在会话哈希中。 在处理用户sign_in的控制器中,您必须执行以下操作:

 #in SessionsController(for example) def create user = User.find_by(email: params[:session][:email].downcase) if user && user.authenticate # logic for authentication session[:user_id] = user.id redirect_to root_path, notice: "Successful sign in." else flash.now[:error] = "Invalid email/password combination" render :new end end 

记下将user_id分配给会话密钥:会话哈希中的user_id。 现在,在application_helper或sessions_helper中定义current_user以便所有视图都可以访问:

 def current_user User.find(session[:user_id]) if session[:user_id] end 

现在迭代所有特定用户的产品:

  <% current_user.products.each do |product| %>  <%= product.userid %> <%= product.product_name %> <%= product.product_link %> 

只要您在用户和产品模型中有has_many :products关联具有belongs_to :user ,您就可以通过执行上述user.products来调用所有用户的产品。 另请注意,我使用’snake_case’作为产品的方法/属性。 Ruby中的惯例是将snake_case用于方法名称和变量。 如果您将列命名为productName和productLink,则必须重命名它们才能使用’snake_case’。 在Ruby中,CamelCase用于Class和ModuleNames。

希望有所帮助!