Ruby on rails 在Rails2.x应用程序的两个模型上保持相同的属性同步?

Ruby on rails 在Rails2.x应用程序的两个模型上保持相同的属性同步?,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,我在一个大型Rails 2.3应用程序中工作,我有一个模型的数据,希望转移到另一个模型。我需要做这件事,因为Rails代码库中有一些地方正在读写模型数据,而外部应用程序通过SQL直接读取表数据。在我删除一个模型和一个表之前,我需要在两个模型及其关联的表上同步属性一段时间 我的模型有一个有一个并且属于这样的关系: class User < ActiveRecord::Base has_one :user_email, :inverse_of => :user accepts_n

我在一个大型Rails 2.3应用程序中工作,我有一个模型的数据,希望转移到另一个模型。我需要做这件事,因为Rails代码库中有一些地方正在读写模型数据,而外部应用程序通过SQL直接读取表数据。在我删除一个模型和一个表之前,我需要在两个模型及其关联的表上同步属性一段时间

我的模型有一个
有一个
并且
属于这样的关系:

class User < ActiveRecord::Base
  has_one :user_email, :inverse_of => :user
  accepts_nested_attributes_for :user_email
  validates_presence_of :email

  def email=( value )
    write_attribute(:email, value)
    user_email.write_attribute(:email, value)
  end
end

class UserEmail < ActiveRecord::Base
  belongs_to :user, :inverse_of => :user_email
  validates_presence_of :email

  def email=( value )
    write_attribute(:email, value)
    user.write_attribute(:email, value)
  end
end
我希望找到一种方法暂时继续允许这种代码

我想不出一种方法来确保保存
User
的实例可以确保提交相应的
UserEmail
数据保存
UserEmail
的实例可以确保提交相应的
User
实例数据,而不会在调用中创建无限的保存循环背

这是我希望目前能够支持的流程:

params = { user: { email: 'foo@bar.com', user_email: { email: 'foo@bar.com' } } }
user = User.create( params )
user.email = "moo@bar.com"
user.save
puts user.user_email # puts "moo@bar.com"
user.user_email.email = "foo@bar.com"
user.user_email.save
user.reload
puts user.email # puts "foo@bar.com"
有没有办法在
用户
用户电子邮件
模型之间实现这种同步,以便它们保持同步?


如果有帮助的话,我可能可以在
user
上取消
accepts\u nested\u attributes\u for:user\u email
accepts\u nested\u attributes\u,让我们假设,为了理智起见,模型是“user”和“Cart”,共享字段是“email”。我会这样做:

#in User
after_save :update_cart_email

def update_cart_email
  if self.changes["email"]
    cart = self.cart
    if cart.email != self.email
      cart.update_attributes(:email => self.email)
    end
  end
end

#in Cart
after_save :update_user_email

def update_user_email
  if self.changes["email"]
    user = self.user
    if user.email != self.email
      user.update_attributes(:email => user.email)
    end
  end
end    
因为我们检查另一个模型的电子邮件是否已经设置,所以它不应该陷入循环中


如果您删除
接受用户电子邮件的\u嵌套的\u属性,则此操作有效。否则,您将得到一个永不结束的保存循环。

出于理智考虑,让我们假设模型是“用户”和“购物车”,共享字段是“电子邮件”。我会这样做:

#in User
after_save :update_cart_email

def update_cart_email
  if self.changes["email"]
    cart = self.cart
    if cart.email != self.email
      cart.update_attributes(:email => self.email)
    end
  end
end

#in Cart
after_save :update_user_email

def update_user_email
  if self.changes["email"]
    user = self.user
    if user.email != self.email
      user.update_attributes(:email => user.email)
    end
  end
end    
因为我们检查另一个模型的电子邮件是否已经设置,所以它不应该陷入循环中

如果您删除
接受:user\u email的\u嵌套的\u属性
,则此操作有效,否则您将得到一个永不结束的保存循环。

使用 在用户模型中

after_save :sync_email, :if => :email_changed?
def sync_email
  user_email.update_column(:email, email) if user_email.email != email
end
在用户电子邮件模型中

after_save :sync_email, :if => :email_changed?
def sync_email
  user.update_column(:email, email) if user.email != email
end
使用 在用户模型中

after_save :sync_email, :if => :email_changed?
def sync_email
  user_email.update_column(:email, email) if user_email.email != email
end
在用户电子邮件模型中

after_save :sync_email, :if => :email_changed?
def sync_email
  user.update_column(:email, email) if user.email != email
end

我已经更新了问题,将
User
UserEmail
用作类名。希望这更清楚。我还更明确地表示,我希望模型永远不会漂移,因此我在这两个类中都重载了
email=
。在您上面的代码中,如果我要依赖
.changes[“email”]
的话,我很确定我必须接受
email
会在模型上漂移,而不会在模型上过载
email=
,对吧?我不知道您所说的“漂移”是什么意思。在保存之前,它们的值不会相同。保存前,它们可能会有所不同。虽然我可能可以用类似的逻辑来解决这个问题,并重写getter。但是,如果您按照“更改对象a的电子邮件”、“对对象B执行某些操作”、“保存对象a”的顺序执行操作,这似乎不太可能。我已将问题更新为使用
User
UserEmail
作为类名。希望这更清楚。我还更明确地表示,我希望模型永远不会漂移,因此我在这两个类中都重载了
email=
。在您上面的代码中,如果我要依赖
.changes[“email”]
的话,我很确定我必须接受
email
会在模型上漂移,而不会在模型上过载
email=
,对吧?我不知道您所说的“漂移”是什么意思。在保存之前,它们的值不会相同。保存前,它们可能会有所不同。我可能可以用类似的逻辑来解决这个问题,并覆盖getter。但是,如果您按照“更改对象a的电子邮件”、“使用对象B执行某些操作”、“保存对象a”的顺序执行操作,那么这将是一个问题,这似乎不太可能。