rails模块实例变量是否可用于其他类?

时间:2014-10-22 21:21:11

标签: ruby-on-rails ruby

我一直在关注教科书并构建一个简单的RoR应用程序。令我困惑的一件事是,似乎模块中的变量以某种方式由控制器访问,包含它而没有任何访问器。这是模块:

   module CurrentCart
  extend ActiveSupport::Concern

  private
    def set_cart
      @cart = Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
      @cart = Cart.create
      session[:cart_id] = @cart.id
    end

end

和控制器调用它

class LineItemsController < ApplicationController

  include CurrentCart
  before_action :set_cart, only: [:create]
  before_action :set_line_item, only: [:show, :edit, :update, :destroy]
  ....
  def create
    @product = Product.find(Params[:prouct_id])
    @line_item = @cart.line_items.build(product: product)
 ...
end
你看到了吗? @cart正在使用它可以访问的变量。我对Ruby和Rails都很陌生,但有人可以解释一下这是可能的吗?

感谢

3 个答案:

答案 0 :(得分:5)

在类中包含一个模块会扩展该类,以包含模块的方法和实例变量(至少已经设置过的那些)。在这种情况下,@ cart在控制器中可用,因为a)已包含模块,b)有一个调用set_cart方法(设置@cart)的before_action。

一旦包含它,您基本上可以将模块的内容视为直接出现在控制器中。这并不完全正确,因为当方法被提取到模块中时,您有机会在类中覆盖它们,但是为了您的情况,它仍然存在。

编辑以澄清:您不需要访问者,因为模块的方法和ivars属于控制器类的同一个实例。

答案 1 :(得分:1)

首先,您使用的条款不正确。 @my_var = 1设置实例(!)变量,而my_var = 1声明并设置局部变量。实例变量属于对象,并且始终可以在其中访问。局部变量只能在声明它们的上下文中访问。

现在关于include。长篇短include将您的模块添加到类层次结构中,因此您可以将其视为“类似继承”。所以在你的代码中@cart不是模块的实例变量,它是一个对象的实例变量,类定义包含你的模块。 如果您需要详细信息,请阅读文章。 http://tech.pro/tutorial/1149/understanding-method-lookup-in-ruby-20

最后,rails helper before_action介入并调用在执行操作之前列出的方法。

答案 2 :(得分:-1)

没有。您必须在模块中为此提供方法

module CurrentCart
  extend ActiveSupport::Concern

  def create_line_items(product)
     @cart.line_items.build(product: product)
  end

  private
    def set_cart
      @cart = Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
      @cart = Cart.create
      session[:cart_id] = @cart.id
    end

end

class LineItemsController < ApplicationController

  include CurrentCart
  before_action :set_cart, only: [:create]
  before_action :set_line_item, only: [:show, :edit, :update, :destroy]
  ....
  def create
    @product = Product.find(Params[:prouct_id])
    @line_item = create_line_items(@product)
 ...
end