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
我想从酒吧内部更改 Foo 的"val"值。
正如您所知,我正在尝试这样做,因为我想通过 Clear(0.8.2(旧,我知道((中的 Facebook Canvas 应用程序添加用户身份验证。我要更改的变量是 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保存到我的数据库中。
谢谢!
在 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
存在,因此它优先。
我会说这是糟糕的语言设计:如果没有self
就不能调用 setter,为什么它应该适合 getter - 特别是当它可能导致像上面这样摇摇欲坠、上下文敏感的代码时? 但这是我们必须使用的,它导致了一些一般准则:
- 如果可以,请使用
@foo
. 很明显,这是做什么的。 - 如果您使用的是吸气剂或二传手,请始终使用
self
,即使不是绝对必要的。 这让你的电话一目了然。 它还保证,如果以后添加具有相同名称的本地,代码的行为不会有所不同。 - 如果你做 1 和 2,你可以假设任何没有
@
或self
的东西都是局部变量(或函数调用,但你可以通过名称区分它们(。
这最终有点冗长,但我无法找到要链接的getter/setter/本地问题的良好演示。 所以也许就是这样 - 希望它有帮助!