0
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”值。

正如您所知,我正在尝试这样做,因为我想通过 Clearance 中的 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 发送到我的应用程序保存到我的数据库中。

谢谢!

4

1 回答 1

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还不存在,所以 ruby​​ 做了“次优”的事情并调用了 getter。但是在第 5 行,本地foo存在,所以它优先。

我会说这是糟糕的语言设计:如果没有 就不能调用 setter self,为什么 getter 应该没问题——尤其是当它可能导致像上面这样摇摇晃晃的、上下文敏感的代码时?但这是我们必须使用的,它导致了一些一般准则:

  1. 如果可以,请使用@foo. 很明显这是做什么的。
  2. 如果您使用的是 getter 或 setter,请始终使用self,即使它不是绝对必要的。这使您的通话内容一目了然。如果您稍后添加具有相同名称的本地,它还可以保证您的代码不会有不同的行为。
  3. 如果您执行 1 和 2,您可以假设没有 a@或 a的任何内容self都是局部变量(或函数调用,但您可能可以通过名称将它们区分开来)。

这最终有点冗长,但我无法找到一个很好的示例来链接到 getter/setter/local 问题。所以也许就是这样 - 希望它有帮助!

于 2012-09-12T19:54:38.463 回答