今晚与我的一位同事就Rails中的方法与属性进行辩论。我发誓我以前见过这个,除非我疯了。这是一个例子:
我们有一个用户模型,我们希望在保存记录之前确定我们有一个名字和一个姓氏。我讨厌回调,但是对于这个例子,让我们说它是在before_save回调中。
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
所以,我很好奇如果调用方法“set_first_last”并且它看到用户的属性first_name为空它将调用方法“first_name”,对吗?用户的first_name属性与名为“first_name”的方法不同。因此,名为“first_name”的用户对象上的属性与Rails中名为“first_name”的用户类上的方法不同,对吗?这就像一个类级方法vs一个实例方法?只是想确定我是正确的,我正确地解释了这一点。
感谢
- 麦克
答案 0 :(得分:1)
我认为你误读了这段代码:
def set_first_last
first_name if self.first_name.blank?
last_name if self.last_name.blank?
end
此代码调用first_name
方法,如果为空,则再次调用first_name
方法(换句话说,此方法的if
部分无意义)
构造此代码的方式,将永远不会使用first_name和last_name属性的值(除非您在查询中使用它们) - 只要您执行user.first_name
,它就会从中重构它name
。一个更常见的模式是将名称设置为类似ensure_first_name
的方法(基本上任何不与getter同类的东西)
实例变量(例如@foo)与同名方法不同,尽管foo
和foo=
通常用于获取/设置实例变量的方法名称。也许你在考虑那个?在某种情况下,Activerecord模型的属性不会存储在单个实例变量中。
答案 1 :(得分:0)
要回答我认为理解的部分:是的,模型上的属性与方法完全不同。
例如,使用用户模型,用户控制器及其相应的视图之一。让我们假设用户模型本身包含first_name
,last_name
和email
属性:
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
当您在控制器中使用该模型的实例时,它看起来像这样:
class UsersController < ApplicationController
def index
#Let's just grab a random user
@user = User.find(1)
end
end
最后,在您的视图中,您可以通过以下方式访问您的属性(属性):
####views/users/index.html.haml####
.random-class
= "You're logged in as #{@user.first_name}!"
但我们也可以在视图中调用User 方法。继续我们的最后一个例子,我们可以添加这样的东西:
####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!'
简而言之,你是正确的,属性和方法是非常不同的,虽然它们有时看起来很相似。
最后,值得指出的是实例方法就是:在类的实例上调用方法,而在实际模型对象上调用类方法,不是该模型对象的单一实例。 Here's a great link to learn more about the differences.
希望这有帮助!
答案 2 :(得分:0)
是的,你解释的是正确的。 您的编码将起作用并分配first_name&amp; last_name与拆分表单。 此外,您也可以用这种方式编写代码(假设您的全名包含2个以空格分隔的单词)
#user.rb
class user
before_save :assign_individual_names
private
def assign_individual_names
first_name, last_name = name.split(' ')
end
end