Rails 3:无限的SQL查询?

| 我将用户模型更改为accept_nested_attributes_for Profile,并且我试图同时创建User和Profile。我正在使用Devise进行身份验证。 这似乎正在工作-除了一个巨大的陷阱... 每次我创建一个新用户时,它都会用“非法指令”使应用程序崩溃,并且当我检查日志时,它看起来像这样...
Started POST \"/users\" for 127.0.0.1 at 2011-04-18 21:01:54 -0500
  Processing by UsersController#create as HTML
  Parameters: {\"utf8\"=>\"‚úì\", \"authenticity_token\"=>\"Rua6PUxnE4a4TvaFcVMfmycw8Y9AFRjEsXVrqwWC2EM=\", \"user\"=>{\"email\"=>\"_______________________@gmail.com\", \"password\"=>\"[FILTERED]\", \"password_confirmation\"=>\"[FILTERED]\", \"profile_attributes\"=>{\"first_name\"=>\"Name\", \"last_name\"=>\"Tester\"}, \"student_claimed\"=>\"false\", \"school\"=>\"\", \"invite_code\"=>\"Texas!\", \"terms_of_service\"=>\"1\"}, \"commit\"=>\"Create Account!\"}
  [1m[35mSQL (0.3ms)[0m   SELECT name
 FROM sqlite_master
 WHERE type = \'table\' AND NOT name = \'sqlite_sequence\'
  [1m[36mSQL (0.3ms)[0m  [1m SELECT name
 FROM sqlite_master
 WHERE type = \'table\' AND NOT name = \'sqlite_sequence\'
[0m
  [1m[35mUser Load (0.2ms)[0m  SELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) LIMIT 1
  [1m[36mInvitation Load (0.1ms)[0m  [1mSELECT \"invitations\".* FROM \"invitations\" WHERE \"invitations\".\"code\" = \'Texas!\' LIMIT 1[0m
  [1m[35mUser Load (0.1ms)[0m  SELECT \"users\".* FROM \"users\" WHERE \"users\".\"confirmation_token\" = \'duALIT6yCL5ShpMvbw79\' LIMIT 1
  [1m[36mRole Load (0.3ms)[0m  [1mSELECT \"roles\".* FROM \"roles\" WHERE \"roles\".\"name\" = \'member\' LIMIT 1[0m
  [1m[35mAREL (0.3ms)[0m  UPDATE \"invitations\" SET \"remaining_uses\" = 9993, \"updated_at\" = \'2011-04-19 02:01:54.506243\' WHERE \"invitations\".\"id\" = 1
  [1m[36mAREL (0.2ms)[0m  [1mINSERT INTO \"users\" (\"email\", \"encrypted_password\", \"reset_password_token\", \"remember_token\", \"remember_created_at\", \"sign_in_count\", \"current_sign_in_at\", \"last_sign_in_at\", \"current_sign_in_ip\", \"last_sign_in_ip\", \"created_at\", \"updated_at\", \"plan_code\", \"confirmation_token\", \"confirmed_at\", \"confirmation_sent_at\", \"student_claimed\", \"student_confirmed\", \"school\", \"invitation_id\") VALUES (\'_______________________@gmail.com\', \'$2a$10$7qzC7T6b1kLiXvPSkMRkduCFClBznDWnnOu7I1ssU8blB9NMJznn2\', NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, \'2011-04-19 02:01:54.509656\', \'2011-04-19 02:01:54.509656\', NULL, \'duALIT6yCL5ShpMvbw79\', NULL, \'2011-04-19 02:01:54.437796\', \'f\', \'f\', \'\', 1)[0m
  [1m[35mSQL (0.1ms)[0m  INSERT INTO \"roles_users\" (\"role_id\", \"user_id\") VALUES (3, 6)
Rendered devise/mailer/confirmation_instructions.html.erb (0.9ms)

Sent mail to _________@gmail.com (1966ms)
Date: Mon, 18 Apr 2011 21:01:55 -0500
From: __________
Reply-To: ___________
To: _____________
Message-ID: <4daced1352c84_1ff5817d6b04978cd@Titan.local.mail>
Subject: Please confirm your email address
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<p>Name,</p>

<p>You registered with the email address: _________@gmail.com. You can confirm your account through the link below:</p>

<p><a href=\"http://localhost:3000/users/confirmation?confirmation_token=duALIT6yCL5ShpMvbw79\">Confirm my account</a></p>

<p>Thanks for signing up!</p>

  [1m[36mAREL (0.2ms)[0m  [1mINSERT INTO \"profiles\" (\"first_name\", \"last_name\", \"created_at\", \"updated_at\", \"user_id\", \"avatar_file_name\", \"avatar_content_type\", \"avatar_file_size\", \"avatar_updated_at\", \"address1\", \"city\", \"state\", \"country\", \"zip\") VALUES (\'Name\', \'Tester\', \'2011-04-19 02:01:57.266502\', \'2011-04-19 02:01:57.266502\', 6, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)[0m
[paperclip] Saving attachments.
  [1m[35mUser Load (0.1ms)[0m  SELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) AND (\"users\".id <> 6) LIMIT 1
  [1m[36mUser Load (1.6ms)[0m  [1mSELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1[0m
  [1m[35mProfile Load (1.6ms)[0m  SELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) AND (\"users\".id <> 6) LIMIT 1[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) AND (\"users\".id <> 6) LIMIT 1
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) AND (\"users\".id <> 6) LIMIT 1[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"users\".\"id\" FROM \"users\" WHERE (LOWER(\"users\".\"email\") = LOWER(\'_______________________@gmail.com\')) AND (\"users\".id <> 6) LIMIT 1
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1[0m
  [1m[35mCACHE (0.0ms)[0m  SELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)

  ... and so on for about 100 more lines ...

  [1m[35mCACHE (0.0ms)[0m  SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 6 LIMIT 1
  [1m[36mCACHE (0.0ms)[0m  [1mSELECT \"profiles\".* FROM \"profiles\" WHERE (\"profiles\".user_id = 6)[0m
  [1m[36mSQL (0.3ms)[0m  [1m SELECT name
因此,这在我开始接受嵌套属性之前并没有发生……我对现在为什么发生这种情况感到非常困惑。是否有人对如何调试和解决问题有任何见识? 谢谢! - 编辑 - 用户模型:
class User < ActiveRecord::Base
  # RELATIONSHIPS
  has_one :profile, :dependent => :destroy
  has_many :photos
  has_many :votes
  has_many :voted_photos, :through => :votes, :source => :photo
  has_many :ratings
  has_many :rated_photos, :through => :ratings, :source => :photo
  has_many :comments
  has_and_belongs_to_many :roles
  has_many :assignments
  has_many :collections, :through => :assignments
  belongs_to :invitation

  accepts_nested_attributes_for :profile

  # VIRTUAL ATTRIBUTES
  attr_accessor :invite_code

  # AUTHENTICATION
  devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :confirmable

  # SECURITY
  attr_accessible :email, :password, :password_confirmation, :remember_me, :confirmed_at, :invite_code, :student_claimed, :school, :terms_of_service, :profile_attributes

  # FILTERS
  before_create :set_role_to_member, :set_invitation
  after_save :update_recurly_account, :unless => Proc.new { Rails.env.test? }

  # VALIDATIONS
  validates_acceptance_of :terms_of_service, :message => \"You must agree to the terms of service in order to create an account.\"
  validate :invitation_status, :on => :create
  validates_presence_of :profile
  validates_associated :profile

  # DELEGATES
  delegate  :first_name, :last_name, :full_name,
            :to => :profile,
            :allow_nil => true

  # ROLES
  def set_role_to_member
    self.roles << Role.find_by_name(\'member\')
  end

  def has_role?( r )
    !roles.find_by_name( r ).nil?
  end

  def list_roles
    list = []
    roles.all.each do |r|
      list << r.name
    end
    list.join(\', \')
  end

  # DEVISE RELATED
  # Hook up recurly account after confirmation
  def confirm!
    self.setup_recurly_account unless Rails.env.test?

    if student_claimed && validate_student_email
      self.student_confirmed = true
      self.save
    end

    super
  end

  protected
  # Don\'t require password on update
  def password_required?
    !persisted? || password.present? || password_confirmation.present?
  end

  public

  # RECURLY RELATED

  def setup_recurly_account
    ...
  end

  private

    def update_recurly_account
      ...
    end

    def validate_student_email
      self.email =~ /\\.edu$/ ? true : false
    end

    def invitation_status
      ...
    end

    def set_invitation
      ...
    end

end
轮廓模型
class Profile < ActiveRecord::Base
  include Helpers::AssetStorage

  # RELATIONSHIPS
  belongs_to :user

  stores_file_as :avatar,
                    :styles =>  { :tenth => \"87x87#\", :eighth => \"106x106#\" },
                    :filename_interpolation => \"avatars/:user_id/:id_:style.:extension\",
                    :default_url => \'/images/no_avatar_:style.png\'

  # VALIDATIONS
  validates_presence_of :first_name, :last_name

  # CALLBACKS
  after_update :save_user

  def full_name
    [first_name,last_name].join(\" \")
  end

  private

    def save_user
      self.user.save!
    end

end
已邀请:
对于
Profile
模型,您不需要
save_user
回调。 进行
user.save
时,将自动保存
user.profile
。由于进行了回调,ѭ6被保存,并调用它的用户再次保存。而用户保存后,它也保存了他的个人资料... 那就是循环。 因此,最简单的修改是删除Profile模型中的after_update回调。 如果只想保存配置文件,请使用
profile.save
。如果用户对象也有更新,请使用
user.save
profile.user.save

要回复问题请先登录注册