Ruby on rails 轨道3和x2B;粘合(合并)实例
下面是一个例子 class Foos has_many :bars belongs_to :cities end class Bar belongs_to :foo end 福斯班 有很多酒吧吗 属于:城市 结束 分类栏 属于:富 结束 所以,如果我有一个名为“Foo1”的Foo实例,它属于编号为1的城市,还有另一个名为“Foo1”的Foo实例,它也属于编号为1的城市,那么如果它们都有不同的条,那么我如何将它粘合到一个Foo实例上,这个Foo实例将包含所有这些条 Thx。最好的备份是foo1,foo2=Foo.where(:name=>“foo1”,city\u id=>some\u id)。限制(2)Ruby on rails 轨道3和x2B;粘合(合并)实例,ruby-on-rails,ruby,ruby-on-rails-3,activerecord,ruby-on-rails-3.2,Ruby On Rails,Ruby,Ruby On Rails 3,Activerecord,Ruby On Rails 3.2,下面是一个例子 class Foos has_many :bars belongs_to :cities end class Bar belongs_to :foo end 福斯班 有很多酒吧吗 属于:城市 结束 分类栏 属于:富 结束 所以,如果我有一个名为“Foo1”的Foo实例,它属于编号为1的城市,还有另一个名为“Foo1”的Foo实例,它也属于编号为1的城市,那么如果它们都有不同的条,那么我如何将它粘合到一个Foo实例上,这个Foo实例将包含所有这些条 Thx。最好的备份是fo
foo1, foo2 = Foo.where(:name => "Foo1", :city_id => some_id).limit(2)
foo1.bars << foo2.bars
foo2.bars = []
foo2.delete
foo1.bar创建了有助于
module Merge
# True if self is safe to merge with +object+, ie they are more or less equal.
# Default implementation compares all attributes except id and metadata.
# Can be overridden in specific models that have a neater way of comparison.
def merge_equal?(object)
object.instance_of?(self.class) and merge_attributes == object.merge_attributes
end
MERGE_INDIFFERENT_ATTRIBUTES = %w(id created_at updated_at).freeze
MERGE_EXCLUDE_ASSOCIATIONS = [].freeze
# Attribute hash used for comparison.
def merge_attributes
merge_attribute_names.inject({}) do |attrs, name|
attrs[name] = self[name]
attrs
end
end
# Names of the attributes that should be merged.
def merge_attribute_names
attribute_names - MERGE_INDIFFERENT_ATTRIBUTES
end
# Names of associations excluded from the merge.
# Override if the model has multiple scoped associations,
# that can all be retrieved by a single has_many association.
def merge_exclude_associations
MERGE_EXCLUDE_ASSOCIATIONS
end
# Merge this object with the given +objects+.
# This object will serve as the master,
# blank attributes will be taken from the given objects, in order.
# All associations to +objects+ will be assigned to +self+.
def merge!(*objects)
transaction do
merge_attributes!(*objects)
merge_association_reflections.each do |r|
local = send(r.name)
objects.each do |object|
if r.macro == :has_one
other = object.send(r.name)
if local and other
local.merge!(other)
elsif other
send("#{r.name}=", other)
end
else
other = object.send(r.name) - local
# May be better to compare without the primary key attribute instead of setting it.
other.each {|o| o[r.foreign_key] = self.id}
other.reject! {|o| local.any? {|l| merge_if_equal(l,o) }}
local << other
end
end
end
objects.each {|o| o.reload and o.destroy unless o.new_record?}
end
end
def merge_attributes!(*objects)
blank_attributes = merge_attribute_names.select {|att| self[att].blank?}
until blank_attributes.empty? or objects.empty?
object = objects.shift
blank_attributes.reject! do |att|
if val = object[att] and not val.blank?
self[att] = val
end
end
end
save!
end
private
def merge_association_reflections
self.class.reflect_on_all_associations.select do |r|
[:has_many, :has_one, :has_and_belongs_to_many].include?(r.macro) and
not r.options[:through] and
not merge_exclude_associations.include?(r.name.to_sym)
end
end
def merge_if_equal(master, object)
if master.merge_equal?(object)
master.merge!(object) ; true
end
end
end
ActiveRecord::Base.class_eval { include Merge }
# Compatibility with ActiveRecord 2.x
class ActiveRecord::Reflection::AssociationReflection
alias :foreign_key :primary_key_name unless method_defined? :foreign_key
end
模块合并
#如果self可以安全地与+object+合并,则为True(即它们或多或少相等)。
#默认实现比较除id和元数据之外的所有属性。
#可以在具有更简洁的比较方式的特定模型中覆盖。
def merge_equal?(对象)
(self.class)的object.instance_和merge_属性==object.merge_属性
结束
合并属性=%w(在更新时创建的id)。冻结
合并\u排除\u关联=[]。冻结
#用于比较的属性哈希。
def merge_属性
merge_attribute_names.inject({})do|attrs,name|
attrs[name]=self[name]
属性
结束
结束
#应合并的属性的名称。
def合并属性名称
属性名称-合并属性
结束
#从合并中排除的关联的名称。
#如果模型具有多个作用域关联,则重写,
#所有这些都可以由一个或多个关联检索。
def merge_exclude_关联
合并\排除\关联
结束
#将此对象与给定的+对象+合并。
#此对象将用作主对象,
#将按顺序从给定对象中获取空白属性。
#与+对象+的所有关联都将分配给+self+。
def合并!(*对象)
事务处理
合并属性!(*对象)
合并(U)关联(U)反射(U)。每个do(r)|
本地=发送(r.name)
对象。每个do |对象|
如果r.macro==:有一个
其他=object.send(r.name)
如果是本地和其他
本地,合并!(其他)
埃尔西夫其他
发送(#{r.name}=“,其他)
结束
其他的
其他=object.send(r.name)-本地
#比较时最好不使用主键属性,而不是设置它。
other.each{o|o[r.foreign_key]=self.id}
其他,拒绝!{| o | local.any?{| l | merge|u if|u equal(l,o)}
本地删除一个foo并将其条添加到另一个foo。这就是你要找的吗?不。我可以在城市1中有“Foo1”,在城市2中有“Foo1”,这是不同的foo,我不想粘上。Foo.find_by_name_和_city只返回一条记录我假设您已经有Foo实例,您的问题是将te Bar实例从一个移动到另一个。如果问题是要找到巧合,你必须更好地陈述它。忘记寻找者。您将以任何方式加载Foo实例。然后,一个接一个地应用所描述的过程。所以,我假设rails有很好的粘合方法。因为我在Foo角色中的模型有10个关联。