我将用户模型更改为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.save
或profile.user.save
。