2016-01-12 29 views
0

我有一个ActiveRecord类,它的属性是一个数组(Postgres数组列),我希望数组中的项目是唯一的。覆盖阵列本身发生的方法的最好方法是什么?例如#< <?重写ActiveRecord属性的append方法(<<)

module PgTags 

    def tags=(value) 
    write_attribute :tags, value.uniq 
    end 

end 

class Rule < ActiveRecord::Base 
    include PgTags 
end 

r = Rule.new 
r.tags = %w(one two one) 
puts r.tags # outputs ['one', 'two'] 
r.tags << 'one' 
puts r.tags # should still output ['one', 'two'] 
+0

你使用的是什么版本的ActiveRecord? –

回答

2

当你写r.tags << value你也可以看到像这样r.tags.<<(value)tags方法将返回Array的实例,然后会发生这种情况:array.<<(value)该阵列将收到<<方法,而不是tags属性。

您必须覆盖Array上的<<方法。

最好是退回到r对象,并将add_tags方法添加到Rule以实现您提出的逻辑。什么你问的是可能的,但更复杂的比这来实现:

module PgTags 
    def tags=(value) 
    write_attribute :tags, value.uniq 
    end 

    def add_tags(*t) 
    self.tags = (tags << t).flatten.uniq 
    end 
end 

class Rule < ActiveRecord::Base 
    include PgTags 
end 

r = Rule.new 
r.tags = %w(one two one) 
puts r.tags #=> ['one', 'two'] 
r.tags.add_tags 'one' 
r.tags.add_tags 'three' 
puts r.tags #=> ['one', 'two', 'three'] 

add_tags方法的行为就像当你使用<<但它处理uniq的逻辑和分配新的值给你所期望规则自己的tags属性。

0

一种不同的方法(现在我看到这是Postgres的)将这样的:

class Rule < ActiveRecord::Base 
    before_validation :ensure_tags_unique 

    private 
    def ensure_tags_unique 
    self.tags = self.tags.uniq 
    end 
end 

这样可以使内置AR的<<=功能。

+0

不,PostgreSQL支持标准的SQL数组列,AR也是如此,没有涉及到'serialize' kludge。 –

+0

@ muistooshort我错过了提到Postgres数组列的问题的一部分。现在我学到了关于ActiveRecord的新内容 - 谢谢! –

相关问题