14

Throughout my application self. is not necessary to refer to a User's name. name works fine.

Why does the following code require self to work as intended?

class User< ActiveRecord::Base
    before_save :validate_name

def validate_name
    if self.name.nil? || self.name.empty?
        self.name= "Mr. No Name"
    end
end

By the way, I know that validates_presence_of can be used to prevent the save, but I want to save with a default if no name is given.

Rails 3.0.7.

B Seven
  • 44,484
  • 66
  • 240
  • 385

1 Answers1

24

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.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Sorry, `self.day` was supposed to be `self.name`! I updated the question. – B Seven Apr 12 '12 at 16:08
  • 7
    Nit: Ruby will never take `x = y` to be a method call. It is always a direct variable (or constant, depending on case) assignment. The form `x` (as expression) depends on if there is such an `x` in scope (as a variable) or not. –  Apr 12 '12 at 16:08
  • If `name` and `name=` are added dynamically after the class file is parsed, then are there times when `name` means `self.name` and other times when `name` is a local variable? – B Seven Apr 12 '12 at 16:10
  • And, does that mean that using `self.name` instead of `name` is a best practice? – B Seven Apr 12 '12 at 16:11
  • 2
    @BSeven The expression `name` means "the local variable name" *if and only if* `name` is already bound (assigned to). At all other times it means `self.name`. The expression `name = y` is always an assignment of `y` to *the variable* `name`. I prefer to just avoid overloading names used. `obj.attr = v` is always required for setters. ;-) –  Apr 12 '12 at 16:11
  • 1
    Nit 2: `class` in Ruby is no more "special" than dynamic methods that are added later. It is just an expression and does not "add context" to how Ruby later handles `x` or `x=` (as this will *never* be a method call, even if "defined within the `class` expression".) In any case, still a +1, even if I find the response a wee bit misleading in places :-) –  Apr 12 '12 at 16:16
  • I use `self` a lot out of formality. I don't know if it's a best practice, per-se, but it's no worse than `this` in JavaScript. – tadman Apr 12 '12 at 17:02
  • @pst Perhaps you should edit the answer to reflect your (correct) comments? `:)`. – Andrew Marshall Apr 12 '12 at 18:02