覆盖 ActiveRecord 的追加方法 (<<) 属性
Override append method (<<) of an ActiveRecord property
我有一个 ActiveRecord class,它的 属性 是一个数组(Postgres 数组列),我希望数组中的项目是唯一的。覆盖数组本身发生的方法的最佳方法是什么,例如 #<< ?
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']
写r.tags << value
的时候也可以这样看r.tags.<<(value)
。 tags
方法将 return Array
的一个实例,然后会发生以下情况: array.<<(value)
数组将接收 <<
方法,而不是 tags
属性。
您必须覆盖 Array
上的 <<
方法。
最好退回到 r
对象并向 Rule
添加一个 add_tags
方法来实现您提出的逻辑。您要求的是可能的,但比这更复杂:
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
属性。
另一种方法(现在我看到这是 Postgres)会这样:
class Rule < ActiveRecord::Base
before_validation :ensure_tags_unique
private
def ensure_tags_unique
self.tags = self.tags.uniq
end
end
这保留了 AR 内置的 <<
和 =
功能。
我有一个 ActiveRecord class,它的 属性 是一个数组(Postgres 数组列),我希望数组中的项目是唯一的。覆盖数组本身发生的方法的最佳方法是什么,例如 #<< ?
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']
写r.tags << value
的时候也可以这样看r.tags.<<(value)
。 tags
方法将 return Array
的一个实例,然后会发生以下情况: array.<<(value)
数组将接收 <<
方法,而不是 tags
属性。
您必须覆盖 Array
上的 <<
方法。
最好退回到 r
对象并向 Rule
添加一个 add_tags
方法来实现您提出的逻辑。您要求的是可能的,但比这更复杂:
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
属性。
另一种方法(现在我看到这是 Postgres)会这样:
class Rule < ActiveRecord::Base
before_validation :ensure_tags_unique
private
def ensure_tags_unique
self.tags = self.tags.uniq
end
end
这保留了 AR 内置的 <<
和 =
功能。