在Ruby/Rails模型/控制器中引用关联/属性时,*,self.*和@*之间的差异

Sch*_*lle 11 ruby ruby-on-rails

假设Rails模型具有持久性/非持久性属性,那么引用它们的最佳实践是什么?如果查看公开提供的代码,则会使用不同的模式.

例如,如果您有一个模型与另一个模型的关联.使用self.association_name@association_name有什么区别?.什么是更好的方式?

与在模型中使用attr_accessor:attr定义的非持久属性相同.您可以使用self.attr@attr这两种方法来引用它们.什么是更好的方式?

小智 13

self.x/ self.x=y 始终是方法调用.

(self.x只是糖self.__send__(:x)而且self.x = y真的只是糖self.__send__(:x=, y))

@x,另一方面,仅是指一个实例变量.

使用@x 不适用于AR关联,因为AR仅为其神奇的操作定义x/x=(哪些方法).(AR本质上只是通过这些方法"捕获"意图访问,并通过自己的内部数据结构路由,这些数据结构任何类似命名的实例变量无关.)

attr_accessor允许"访问两种方式" ,因为它只使用同名的实例变量作为它的后备(它必须在某处存储值).考虑attr_accessor :x相当于:

def x; @x; end
def x= (y); @x = y; end
Run Code Online (Sandbox Code Playgroud)

快乐的编码.

  • @Scholle你必须使用`self.x = y`否则Ruby会认为你想把`y`的评估分配到`x`局部变量(它会很乐意做,如果需要的话可以创建它).但是,假设范围内没有变量`x`,那么`self.x`和`x`都会调用`x`方法.有些人喜欢在这种情况下省略`self`(我愿意).最大的问题是*要保持一致*. (2认同)

Adr*_*uio 6

大多数情况下,您更愿意使用attr而不是@attr.这是因为attr如果属性不存在,该方法通常会设置属性.

例如,此模型订单:

model Order
  have_many :items

  def total
    @total ||= items.collect(&:price).sum
  end

  def taxes
    @taxes ||= total * 0.10
  end
end
Run Code Online (Sandbox Code Playgroud)

这个模型工作,如果我使用@total而不是total在方法中taxes,如果我之前没有total在此对象上调用方法,则计算将失败.

由于@pst指出,@association_name对于关联不起作用,你必须使用该方法association_name.

self.attr应该只用于设置一个属性(调用self.attr=),当你读取你最好使用的值时attr,请参阅这篇文章:何时使用自我Rails模型