Mike Riley
Mike Riley

Reputation: 292

Methods vs Attributes Rails

Was debating with a colleague of mine tonight on methods vs attributes in Rails. I swear I have seen this before unless I am crazy. Here is an example:

We have a user model and we want to be certain we have a first name and a last name prior to saving the record. I hate callbacks, but for this example, let's say it is in a before_save callback.

class User     
  before_save :set_first_last

  def set_first_last
    first_name if self.first_name.blank?
    last_name if self.last_name.blank?
  end

  def first_name
    self.first_name = self.name.split(" ").first
  end

  def last_name
    self.last_name = self.name.split(" ").last
  end
end

So, I am curious if the method "set_first_last" name is called and it sees that the attribute first_name on user is blank it will call the method "first_name", correct? The attribute first_name on user is different than a method called "first_name." So an attribute on the user object called "first_name" would be different than a method on the user class called "first_name" in Rails, correct? This would be like a class level method vs an instance method? Just want to be sure I am correct and that I am explaining this correctly.

thanks

--Mike

Upvotes: 0

Views: 1775

Answers (3)

Frederick Cheung
Frederick Cheung

Reputation: 84124

I think you are misreading this bit of the code:

def set_first_last
  first_name if self.first_name.blank?
  last_name if self.last_name.blank?
end

This code calls the first_name method, and if it is blank, calls the first_name method again (in other words the if parts of this method are pointless)

The way this code is constructed, the value of the first_name and last_name attributes will never be used (other than if you were to use them in your queries) - any time you do user.first_name it will reconstruct it from name. A more common pattern would be to have the methods that set the names called something like ensure_first_name (Basically anything that doesn't class with the getter)

Instance variables (eg @foo) are distinct from methods of the same name, although it is of course common for foo and foo= to be the methods for getting/setting an instance variable of that name. Perhaps you were thinking of that? In an event the attributes of an Activerecord model aren't stored in individual instance variables.

Upvotes: 1

Ajay
Ajay

Reputation: 4251

Yes, what you explained is correct. Your piece of coding is going to work and assign the first_name & last_name with the splitted form. further you can write your code in this way as well (assuming your full name consists of 2 words separated by space)

 #user.rb
class user     
  before_save :assign_individual_names

 private 
  def assign_individual_names
    first_name, last_name = name.split(' ')
  end

end

Upvotes: 0

Collin Graves
Collin Graves

Reputation: 2257

To answer the part I think I understand: yes, an attribute on a model is quite different than a method.

Take, for example, a User model, a Users controller, and one of its corresponding views. Let's pretend the User model itself contains first_name, last_name, and email properties:

class User < ActiveRecord::Base
  #Ensure presence of the following before saving model
  validates_presence_of :first_name, :last_name, :email 

  #Verify unique email
  validates_uniqueness_of :email

  #Here's our lone User method...poor guy
  def admin?
    self.company_members.where('? = ANY (company_members.roles)', Role::ADMIN).any?
  end
end

When you get around to working with an instance of that model in your controller, it'll look something like this:

class UsersController < ApplicationController
  def index
    #Let's just grab a random user
    @user = User.find(1)
  end
end

Finally, in your view, your properties (attributes) can be accessed in the following way:

####views/users/index.html.haml####

.random-class
  = "You're logged in as #{@user.first_name}!"

But we can also call User methods in the view as well. Continuing off our last example, we could add something like this:

####views/users/index.html.haml####

.random-class
  = "You're logged in as #{@user.first_name}!"
  - if @user.admin?
    = 'Oh my gosh, our freaking User method worked!'

So in short, you're correct in that properties and methods are very different, although they look similar at times.

Lastly, it's worth pointing out that instance methods are just that: methods called on instances of a class, whereas class methods are called on an actual model object, and not a singular instance of that model object. Here's a great link to learn more about the differences.

Hope this helps!

Upvotes: 0

Related Questions