nonopolarity
nonopolarity

Reputation: 150996

In Ruby, how to write code inside a class so that getter foo and setter self.foo = ... look more similar?

In Ruby, inside a class's instance method, we use a getter by

foo

and we use a setter by

self.foo = something

One doesn't need to have a self. and the other does, is there a way to make them look more similar, and not using something like self.foo as the getter, as it also looks verbose.

(update: note that getter and setter may simply get or set an instance variable, but they might also do a lot of work, such as going into the DB and check the existence of a record and if not, create it, etc)

Upvotes: 3

Views: 816

Answers (3)

Matheus Moreira
Matheus Moreira

Reputation: 17020

Since local scope takes precedence, when you say foo = something, a local variable foo will be created and assigned the contents of something.

The reason you can write foo in order to use the getter is because Ruby will move up in scope when it can't find a variable with that name and it will eventually find the method.

If there is a local variable with the same name as the getter method, Ruby will use its value instead:

class Foo

  attr_accessor :foo

  def initialize
    @foo = :one
  end

  def f
    foo = :two
    foo
  end
end

Foo.new.f
# => :two

In order to make it clear that you want to access the setter, you must write self.foo = something. That will tell Ruby you want to execute the foo= method on the self object with something as parameter.

Upvotes: 10

Mladen Jablanović
Mladen Jablanović

Reputation: 44080

If you are willing to break the conventions, you can write your setters using jQuery style, using the same method for getter and setter, depending of whether it has arguments or not:

def foo *args
  return @foo if args.empty?
  @foo = args.first
end
# => nil

foo
# => nil 
foo(:bar) # foo = :bar
# => :bar 
foo
# => :bar 

Upvotes: 5

Pete
Pete

Reputation: 18075

As far as I know, there isn't a way around this in Ruby. I'm pretty confident this is simply how Ruby evaluates expressions.

When given a value, Ruby will first check if there is a local variable within the context which matches the one being called. If there is (perhaps 'foo' in your case), that will be the value used. If there is no such value, then Ruby will try to look up the value as a method call (falling through to "self" as the caller). If no such method exists in the look up path, an error will be raised.

The need to use "self" in the setter is to avoid Ruby setting the value as a local variable, while the lack of the use of "self" only works in the getter instance when there is no local variable of the same name being used in that context. It is probably better and clearer, albeit slightly more verbose, to be explicit with your use of self as to avoid confusion about where values are coming from.

Upvotes: 1

Related Questions