Ruby

时间:2015-05-19 19:19:07

标签: ruby

根据this帖子,为了在to_json通话期间保持属性,我们需要执行以下操作:

def attributes
  super.merge('foo' => self.foo)
end

凭借初学者对Ruby的了解,我无法理解以下内容:

  • 每个Ruby类都有attribute方法吗?
  • super.merge在这做什么?它将哪个hashmap附加到?

3 个答案:

答案 0 :(得分:3)

不,每个Ruby类都没有#attributes方法。您正在使用的类可能继承自另一个类或混合在一个模块中(例如ActiveRecord::Base#attributes)。

您定义的属性方法将覆盖任何现有的#attributes方法。在覆盖的情况下,Ruby提供了一个#super方法,该方法调用您要覆盖的原始方法。在这种情况下,您将调用原始#attributes方法,该方法会返回Hash个属性键及其值(例如{ attr1: 'a', attr2: 'b' })。

#merge是一个Hash函数,您在Hash上调用原始#attributes调用返回(例如{ attr1: 'a', attr2: 'b' })。 #merge创建一个新的哈希,包含原始属性哈希以及第二个哈希中提供的键值对。

来自Hash#merge上的Ruby 2.2文档:

  

merge(other_hash)→new_hash单击以切换源

     

merge(other_hash){| key,oldval,newval | block}→new_hash

     

返回一个包含other_hash和的内容的新哈希   hsh的内容。如果未指定块,则条目的值为   重复键将是other_hash的重键。否则值为   通过使用密钥调用块来确定每个重复的密钥,   它在hsh中的值及其在other_hash中的值。

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
h1.merge(h2){|key, oldval, newval| newval - oldval}
               #=> {"a"=>100, "b"=>54,  "c"=>300}
h1             #=> {"a"=>100, "b"=>200}

http://ruby-doc.org/core-2.2.0/Hash.html#method-i-merge

关于您的示例的一些注释:'foo' => self.foo

  • 您无需在self中指定self.foo。仅foo就足够了。这真的只需要分配self.foo = 'whatever'以及您在同一范围内定义另一个foo的情况。
  • 确保您提供的密钥类型与#attributes正在返回的密钥类型相匹配。

案例1:#attributes返回字符串哈希 - >值,因此使用String键合并哈希值(ActiveRecord会这样做。)

{ 'attr1' => 1, 'attr2' => 'b' }.merge( { 'attr3' => '3' }

案例2:#attributes返回符号哈希 - >值,因此使用符号键合并哈希:

{ :attr1 => 1, :attr2 => 'b' }.merge( { :attr3 => '3' }

答案 1 :(得分:2)

attributes是由ActiveRecord提供的方法。如果你单击source,你会注意到它实际上只是公开了@attributes的实例变量hash(因为它可以nil通过哈希强制执行哈希.to_hash)。

class ActiveRecord::Base
  def attributes
    @attributes.to_hash
  end
end

我们将调用此方法parent,因为我们将在我们的课程中扩展其行为。这可以通过inheritance

来实现
class Person < ActiveRecord::Base
  def attributes
    super.merge('foo' => self.foo)
  end
end

attributes现在调用父方法[Activerecord::Base].attributes并向哈希添加新密钥。 此代码大致相同,应该更易于阅读。

class Person < ActiveRecord::Base
  def attributes
    attrs = super # eg. { name: "x", created_at: [...], [...] }
    attrs[:foo] = self.foo # eg. { name: "x", foo: [...], ... }
    attrs
  end
end

答案 2 :(得分:0)

属性是您班级的同义词属性,变量等。并非所有类都包含属性,但通常存在数据模型来封装它们包含的属性和方法,以及修改和/或操作它们的一些行为。要使用模型的json表示来响应,通常在控制器中执行类似的操作。

respond_to :json
def tags
  render :json => User.find(params[:id]).tags
end