lewstherin
lewstherin

Reputation: 370

Setting parameters in before_save

This is not so much a how-to question but is more of a why question. Consider the example below, where I am trying to set a default email in before save.

class Organization < ActiveRecord::Base
  before_save :set_default_email

  def set_default_email
    email ||= 'info@'+ domain
  end
end

The above method unfortunately does not work. Instead if add a self like shown below, it works fine and the value gets passed on to the db.

  def set_default_email
    self.email ||= 'info@'+domain
  end

However, given that the default receiver in ruby is self (which is why it understands domain etc.), shouldn't self.email and email be the same thing?

Upvotes: 2

Views: 1307

Answers (3)

Max Williams
Max Williams

Reputation: 32933

Just to expand on the other answers a bit, if you break down ||= you get

email = email || 'info@'+ domain

which is equivalent to

email = self.email || 'info@'+ domain

self.email is nil, so it will evaluate to

email = 'info@'+ domain

And that's set a local variable, but doesn't call the email= method.

This is one reason why it's good practice to ALWAYS use self. rather than rely on Ruby's default scoping. It's also much more readable: another coder scanning your code can easily see that when you do self.email = (or self.email ||= in your case) you're calling the setter method, rather than defining a local variable.

Upvotes: 2

Fer
Fer

Reputation: 3347

if you don't use self. what you are doing is defining a local variable, instead of calling the setter

Upvotes: 1

Marek Lipka
Marek Lipka

Reputation: 51151

No, Ruby assumes construction variable = value to be local variable assignment. That's why in setter method, you have to point receiver explicitly.

Upvotes: 2

Related Questions