rails自动保存使用where / find_by

时间:2015-07-03 00:39:41

标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord

我有一个特殊情况,我需要知道最佳做法。

给出一个简单的has_many关联:

class Authentication < ActiveRecord::Base
  belongs_to :user
  #provider can be :password, :facebook_oauth etc
  #code is the encrypted password on provider == :password
end


class User < ActiveRecord::Base
  has_many :authentications

  #this works
  def encrypted_password=(pw) 
    set = false
    self.authentications.each do |auth|
      if auth.provider.to_sym == :password
        set = true
        auth.code = pw
      end
    end
    self.authentications.build(provider: :password, code: pw) unless set
    pw
  end

  #this only when no password-auth exist yet
  def encrypted_password=(pw) 
    self.authentications.find_or_initialize_by(provider: :password).code = pw
  end
end

然后

user = User.last
user.password="abcdefg"
user.save

当第一个解决方案有效时,它会加载并迭代所有相关的Authentication对象。这是一种解决方法,但这是不行的。

第二个解决方案在加载现有的Password-Authentication对象时不起作用。 User对象不知道使用find_or_initialize_by方法加载的Authentication对象的更改。更改将不会保存...

有没有办法将更改后的Authentication对象注册回User对象,以便在调用user.save时自动保存?

2 个答案:

答案 0 :(得分:1)

现在似乎无法将找回的对象返回到找回父对象。请参阅此问题https://github.com/rails/rails/issues/17466

我有同样的问题,我的解决方法是,即使这不是你或我想要的,在你自己的方法中使用save并在事务中进行所有保存。

def encrypted_password=(pw)
  self.authentications.find_or_initialize_by(provider: :password).update_attribute(code, pw)
  end

答案 1 :(得分:0)

  

有没有办法将更改后的Authentication对象注册回User对象,以便在调用user.save时自动保存?

如果您的问题只需要知道如何保存关联类,则可以将其添加到类定义中:

class User < ActiveRecord::Base
  has_many :authentications, autosave: true
end

Authentication对象已经通过User列引用回user_id对象,Authentication列应该通过belongs_to方法autosave: true。保存父对象(Authentication)时,此User将保存关联对象15/07/01 04:23:15 INFO mapreduce.Job: Task Id : attempt_1434100146148_0014_m_000000_0, Status : FAILED Error: java.lang.NullPointerException at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.initialize(MapTask.java:525) at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:763) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:340) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:167) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1557) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:162)