Why Isn't Self Always Needed in Ruby/Rails/Activerecord

Why isn't self always needed in ruby / rails / activerecord?

This is because attributes/associations are actually methods(getters/setters) and not local variables. When you state "parent = value" Ruby assumes you want to assign the value to the local variable parent.

Somewhere up the stack there's a setter method "def parent=" and to call that you must use "self.parent = " to tell ruby that you actually want to call a setter and not just set a local variable.

When it comes to getters Ruby looks to see if there's a local variable first and if can't find it then it tries to find a method with the same name which is why your getter method works without "self".

In other words it's not the fault of Rails, but it's how Ruby works inherently.

Hope that helps.

Is it better practice to use attribute_name or self.attribute_name when accessing within model

Camp 1: Convention over configuration. Also, self.first_name will not work for private accessors.

Camp 2: You know what's what at a glance, whereas you might forget what methods you have without the explicit receiver.

In the end, it's an opinion question, so I'm voting to close. However, food for thought:

bbatsov style guide:

Avoid self where not required. (It is only required when calling a self write accessor.)

GitHub style guide (based on bbatsov style guide):

Avoid explicit use of self as the recipient of internal class or instance messages unless to specify a method shadowed by a variable.

Why use self to access ActiveRecord/Rails model properties?

Often the use of self is to force Ruby to recognize that as a method call and not mis-interpret it as a variable. Without prior knowledge of a method called day=, then day = "x" looks to Ruby like a variable assignment. self.day = "x" is always a method call.

The reason this is trouble is because the name and name= methods are added dynamically after the User class file has been parsed. The first thing Rails does when using a model is make methods for the associated database fields, but this happens after your user.rb file is parsed.

Why is 'self' required to call a Ruby method from within its constructor?

Ruby doesn't know if you want to make a local variable named "name" or use the member variable.

self.name tells it you want to use the member variable.

There isn't any syntax for saying you want to create a local variable, so that has to be the default.

(Also, member variables aren't real, but you know what I mean)

Why can't I directly access instance variables in Active Record callback?

can you not access instance variables directly in an Active Record callback?

You can access instance variables from any instance method, including those used as ActiveRecord callbacks.

Also, I haven't defined an accessor function for this particular variable, so what actually happens when I say self.variable or variable (I've tried both, and both work aside from the LHS of an assignment)?

First, it is important to know what the difference between the two syntaxes. variable = 123 will assign the value 123 to a local variable. self.variable = 123 will call a method named variable= on self and pass 123 as an argument.

> class Foo
> def x=(value)
> puts "Foo#x called with #{ value }"
> end
>
> def bar
> x = 123 # local variable assignment, `x` only exists inside the `bar` method.
> self.x = 456 # calls `x=`
> end
> end

> Foo.new.bar
Foo#x called with 456

Something that can be a bit confusing is that methods invoked with an implicit receiver shares the same syntax with referencing a local variable.

> class Bar
> def x
> "In method x"
> end
>
> def foo
> # No local variable `x` has been initialized yet, so references to `x` will call the method with that name.
> puts x # calls method `x` and prints "In method x".
> # This example is equivalent to `puts self.x`.
>
> x = "Hello" # Now that a local variable is defined it will hide the method `x`.
> puts x # references the local variable and prints "Hello".
> puts self.x # calls the method `x` and prints "In method x".
> end
> end

> Bar.new.foo
In method x
Hello
In method x

Second, you need to know that ActiveRecord creates accessor methods for each column of your model's table. Let's say that I have a model User(id: integer, name: string, age: integer). ActiveRecord will define instance methods id, name and age to read the attributes and id=, name= and age= to set the attributes.

Instance variables are something else entirely. You cannot access the database attributes with instance variables like @id, @name, @age.

So does he maybe mean that the callback methods aren't call from a reference to the object?

No, ActiveRecord callbacks do indeed invoke instance methods on the object.

Why is `self` needed inside this instance method?

You don't need it in that case.

You only need to refer to an attribute with self if you're assigning to it, to distinguish it from assigning to a local.

When to use 'self' in Ruby

Whenever you want to invoke a setter method on self, you have to write self.foo = bar. If you just write foo = bar, the ruby parser recognizes that as a variable assignment and thinks of foo as a local variable from now on. For the parser to realize, that you want to invoke a setter method, and not assign a local variable, you have to write obj.foo = bar, so if the object is self, self.foo = bar

How and why should I avoid using self in a Ruby method declaration

There's nothing wrong with using self, but it bypasses the requirement to create a variable instance of your object, so some die-hard OO programmers would suggest avoiding self for that reason. If you avoid "self" then you are forced to initialize your class and assign it to a variable name which forces you think of it as a true object, and not just a collection of functions.

Here's an example class to demonstrate how you would call methods with and without "self"

class StaticVersusObjectMethod

def self.class_method
puts 'Hello, static class method world!'
end

def object_method
puts 'Hello, object-oriented world!'
end

end

# No need to create an object instance variable if the method was defined with 'self'
StaticVersusObjectMethod.class_method

# You must create an object instance variable to call methods without 'self'
object = StaticVersusObjectMethod.new
object.object_method

output:

Hello, static class method world!
Hello, object-oriented world!

Whether you use self in the declaration should depend on the data you want your method to use. If the methods will only operate on the variables you pass in as parameters, then use 'self'. On the other hand, don't use 'self' if you want them to act as true object methods. "True" object methods can operate on the state of the class variables (fields) in the objects which you create and assign to a one or more variable names.

In Ruby, when should you use self. in your classes?

Use self when calling a class's mutator. For example, this won't work:

class Foo
attr_writer :bar
def do_something
bar = 2
end
end

The problem is that 'bar = 2' creates a local variable named 'bar', rather than calling the method 'bar=' which was created by attr_writer. However, a little self will fix it:

class Foo
attr_writer :bar
def do_something
self.bar = 2
end
end

self.bar = 2 calls the method bar=, as desired.

You may also use self to call a reader with the same name as a local variable:

class Foo
attr_reader :bar
def do_something
bar = 123
puts self.bar
end
end

But it's usually better to avoid giving a local variable the same name as an accessor.



Related Topics



Leave a reply



Submit