2012-09-12 154 views
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”值。如何从另一个包含的模块访问包含模块的方法?

就这么你知道,我正在尝试这样做,因为我想通过Facebook上的Canvas应用程序在Clearance(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

我相信'Bar = bar'中的'val = 50'会创建一个局部变量。如果使用'self.val = 50'代替它是否工作? –

+0

你是对的!这样可行。谢谢!你想回答这个问题,所以我可以接受吗? –

+0

会做。我正在寻找我学到的链接,但我似乎无法再找到它......也许我会写出新的权威指南! –

回答

1

在ruby中,表格varname = value的任何语句将创建一个名为varname的本地变量(如果它尚不存在)。 在class类中有一个名称相同的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 完全相同的代码做不同的事情!在第二行,局部变量foo还没有存在,所以ruby做了“下一个最好”的事情,并称为getter。但在第5行中,存在本地foo,因此优先。

我想说这是糟糕的语言设计:如果没有self就不能调用setter,那么为什么它应该适合getter - 尤其是当它可能导致像上面那样的摇摆不定的上下文敏感代码?但这是我们必须处理的,并且它导致了一些一般指导:

  1. 如果可以,请使用@foo。这很明显是什么。
  2. 如果您使用的是吸气剂或吸气剂,请始终使用self,即使并非绝对必要。这让你明白你在打电话。它还可以保证您的代码在以后使用相同名称添加本地时不会有不同的表现。
  3. 如果你做1和2,你可以假设没有@self的任何东西都是局部变量(或函数调用,但你可以通过名字区分这些变量)。

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