Rails 3:无限SQL查询



我将用户模型更改为accept_nested_attributes_for配置文件,并且我正在尝试同时创建用户和配置文件。我正在使用设计验证。

这似乎是工作-除了一个巨大的问题…

每次我创建一个新用户,它崩溃的应用程序"非法指令",当我检查日志它看起来像这样…

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。由于回调,user.profile保存,它调用它的用户再次保存。用户保存,它也保存他的个人资料......

这就是循环。

所以最简单的修改就是删除Profile模型中的after_update回调。

如果只想保存配置文件,请使用profile.save。如果用户对象也有更新,则使用user.saveprofile.user.save

相关内容

  • 没有找到相关文章

最新更新