tags:

views:

240

answers:

4

I have following code

class User
  attr_accessor :name
end

u = User.new
u.name = 'john'
puts u.name #=> john

In the above case everything works. However this code does not work

class User
  attr_accessor :name
end

u = User.new
u.name = 'john'
u.name('john')

In order to fix that issue, I have decided to use alias_method. I know there are other ways to solve the problem, but I'm specifically looking if this problem could be solved using alias_method. Trying to learn.

Following code will work

class User
  attr_accessor :name
  alias_method :foo, :name=
end

u = User.new
u.foo('john')
puts u.name

However this code will not work for obvious reason.

class User
  attr_accessor :name
  alias_method :name, :name=
end

u = User.new
u.name('john')
puts u.name

Anyone knows if this problem can be fixed with alias_method.

+4  A: 

I don't really get what you're trying to do. By writing attr_acccessor :name, the name= method gets created automatically. If you're trying to make this work:

user.name("john")

you can add this method:

class User
   attr_accessor :name
   def name(n)
     self.name = n
   end
end
Geo
You are not writing an answer, maybe it would be bettor of as a comment.
johannes
Kinda hard to add all of this as a comment, don't you think?
Geo
As I stated in my question, I am trying to learn dark sides of alias_method. I attempted to solve a problem in a specific way and I failed. I was wondering if someone has a solution that I missed. That's it. Just learning.
Roger
+2  A: 

The short version is alias method cannot help you here.

It looks like you're trying to merge the getter and setter created by attr_accessor. The reason this isn't working is because you're overriding the getter with the setter when you call alias.

To get the functionality you're looking for you'll have to define your own method.

Something like this:

class User
  attr_accessor :name

  def name(set_value = "VALUE_THAT_WILL_NEVER_BE_USED_AS_A_NAME")
    unless set_value == "VALUE_THAT_WILL_NEVER_BE_USED_AS_A_NAME"
      @name = set_value
    end
    @name
  end

end

u = User.new
u.name('john') #=> sets name to john
puts u.name #=> puts john

# bonus! doesn't override name=

u.name = 'mike' # => sets name to mike
puts u.name #=> puts mike

Edit: Corrected method to allow setting of nil or false.

EmFi
Isn't the if unnessary?def name(set_value)@name = set_value unless set_value.nil?end
CodeJoust
The way I interpreted the question, to mean the poster was looking for a way to get and set with the same method. The if is necessary, but the condition isn't perfect. As it won't let nil or false assign to @name.
EmFi
+1  A: 
class User
  attr_accessor :name
end

u = User.new
u.name = 'john'
u.name('john')

In this code u.name would be the getter for name. It looks like you're trying to call it as a setter? Is that want you want to do? If that's the case then you wouldn't use attr_accessor, you'd need to write the getters and setters yourself.

Rob Cameron
I was just playing with alias_method and wanted to be sure that what I am not able to achieve is not possible. Secondly I got some wonderful answers. Thanks
Roger
+1  A: 

If you want to use a single getter/setter method beware of using "nil" since you may want to set your attribute to nil.



u.name("john")
u.name(nil) # name still will be john

So do something which checks that there are args


class U
  attr_reader :n
  def n(*args)
    if(args.length > 0)
      @n = args.first
    else
      @n
    end
  end
end

u = U.new
u.n "j"
u.n # j
u.n nil
u.n # nil
The Who