Reputation: 292
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
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
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
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