如何从另一个包含的模块中访问包含模块的方法?

时间:2012-09-12 18:41:52

标签: ruby-on-rails ruby facebook clearance

module Foo
  attr_accessor :val
end

module Bar
  def bar
    val = 50
  end
end

class FooBar
  include Foo
  include Bar
end

fb = FooBar.new
puts fb.bar # 50
puts fb.val # nil

我想从Bar内部改变Foo的“val”值。

您知道,我正在尝试这样做,因为我想通过清除中的Facebook Canvas应用程序添加用户身份验证(0.8.2(旧,我知道))。我想要更改的变量是https://github.com/thoughtbot/clearance/blob/b8ccca00d91cb336e044b76b5c6ae1d8de9d2d8d/lib/clearance/authentication.rb#L25

这个模块被包含在ApplicationController中,之后我又包含了另一个模块(FacebookAuthenticationHelper),它有点像

def authenticate_facebook
  current_user ||= facebook_user if coming_from_facebook?
end

我很想知道是否有更好的方法来做到这一点。我没有使用OAuth,我只是将Facebook的user_id发送到我的应用程序,从signed_request发送到我的数据库。

谢谢!

1 个答案:

答案 0 :(得分:1)

在ruby中,任何形式为varname = value的语句都会创建一个名为varname的局部变量(如果它尚不存在)。 在类方法中具有相同名称的setter方法时,情况甚至如此。此外,如果存在局部变量,则它优先于getter和setter。例如:

class Demo
    attr_accessor :foo

    def demonstrate!
        @foo = 1      #1: Set member variable foo, so we get meaningful output
        puts foo      #2: Prints 1 (this calls the getter)
        puts self.foo #3: Prints 1 (also calls the getter)

        foo = 2       #4: Creates a LOCAL variable named foo with the value 2
        puts foo      #5: Prints 2 (locals take precedence over getters)
        puts self.foo #6: Prints 1 (calls the getter - the member variable hasn't changed)

        self.foo = 3  #7: Use SELF to ensure you call a getter or setter
        puts foo      #8: Prints 2 (the local again)
        puts self.foo #9: Prints 3 (the member, which is now 3)
    end
end

关于这个系统的坏处是:看第2行和第5行。相同的代码执行不同的事情!在第2行,局部变量foo尚不存在因此,红宝石做了“次佳”的事情并称之为吸气剂。但是在第5行,本地foo存在,因此它优先。

我会说这是糟糕的语言设计:如果不能在没有self的情况下调用setter,为什么它对于getter来说是可以的 - 特别是当它可能导致摇摇欲坠,上下文敏感的代码时以上?但这是我们必须要合作的,它会产生一些一般性的指导原则:

  1. 如果可以,请使用@foo。这显然是做什么的。
  2. 如果您使用的是getter或setter,请始终使用self,即使这不是绝对必要的。这显然是你所说的。它还保证如果稍后添加具有相同名称的本地代码,则代码的行为将不同。
  3. 如果您执行1和2,您可以假设没有@self的任何内容都是局部变量(或函数调用,但您可以通过名称来区分它们)。
  4. 这最终有点啰嗦,但我无法找到要链接到的getter / setter / local问题的良好演示。也许这就是它 - 希望它有用!