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
I would like to, from within Bar, change Foo’s “val” value.
Just so you know, I’m trying to do this because I want to add user authentication through a Facebook Canvas app in Clearance (0.8.2 (old, I know)). The variable that I want to change is https://github.com/thoughtbot/clearance/blob/b8ccca00d91cb336e044b76b5c6ae1d8de9d2d8d/lib/clearance/authentication.rb#L25.
This module gets included into ApplicationController, and I’m including another module afterwards (FacebookAuthenticationHelper) that does something like
def authenticate_facebook
current_user ||= facebook_user if coming_from_facebook?
end
I would love to know if there’s a better way to do this as well. I’m not using OAuth, I’m just saving Facebook’s user_id sends to my app from signed_request into my DB.
Thanks!
In ruby, any statement of the form
varname = valuewill create a local variable namedvarnameif it doesn’t already exist. This is even true within class methods where the class has a setter method of the same name. Furthermore, if a local variable exists, it takes precedence over getters and setters. For example:The bad thing about this system is: Look at lines 2 and 5. The same exact code does different things! On line 2, the local variable
foodidn’t exist yet, so ruby did the “next best” thing and called the getter. But on line 5, the localfooexists, so it takes precedence.I’d say that this is bad language design: If setters can’t be called without
self, why should it be okay for getters – especially when it can lead to rickety, context-sensitive code like the above? But it’s what we have to work with, and it leads to some general guidelines:@foo. It’s obvious what that does.self, even when it’s not strictly necessary. This makes it obvious what you’re calling. It also guarantees your code won’t behave differently if you add a local with the same name later.@or aselfis a local variable (or a function call, but you can probably tell those apart by name).And that ended up being a bit long-winded, but I was unable to find a good demonstration of the getter/setter/local problem to link to. So maybe this is it – hope it’s helpful!