2013-03-05 131 views
1

我需要對我的設計用戶模型進行一些更改跟蹤。我正在嘗試paper_trail,但它在更改電子郵件和還原時會導致問題。設計可確認的電子郵件和paper_trail的問題

1.9.3p385 :048 > u = User.create email: '[email protected]', password: 'password', username: 'bob' 
    (0.2ms) BEGIN 
    User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY '[email protected]' LIMIT 1 
    User Exists (0.1ms) SELECT 1 AS one FROM `users` WHERE `users`.`username` = BINARY 'bob' LIMIT 1 
    User Exists (0.1ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY '[email protected]' LIMIT 1 
    User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`confirmation_token` = 'zNfBSVLJJ9nF4y5sanVU' LIMIT 1 
    SQL (0.2ms) INSERT INTO `users` (`confirmation_sent_at`, `confirmation_token`, `confirmed_at`, `created_at`, `current_sign_in_at`, `current_sign_in_ip`, `email`, `encrypted_password`, `last_sign_in_at`, `last_sign_in_ip`, `remember_created_at`, `reset_password_sent_at`, `reset_password_token`, `roles_mask`, `sign_in_count`, `unconfirmed_email`, `updated_at`, `username`) VALUES ('2013-03-05 13:15:53', 'zNfBSVLJJ9nF4y5sanVU', NULL, '2013-03-05 13:15:53', NULL, NULL, '[email protected]', '$2a$10$1BrAH1yqgF3qbgkmpMPl/uE0UY792aB8fvYKLksMnyQsn7sM/dY4O', NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, '2013-03-05 13:15:53', 'bob') 
    SQL (0.2ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:15:53', 'create', 9, 'User', NULL, NULL) 
    (1.3ms) COMMIT 
=> #<User id: 9, username: "bob", email: "[email protected]", encrypted_password: "$2a$10$1BrAH1yqgF3qbgkmpMPl/uE0UY792aB8fvYKLksMnyQs...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2013-03-05 13:15:53", updated_at: "2013-03-05 13:15:53", roles_mask: nil, confirmation_token: "zNfBSVLJJ9nF4y5sanVU", confirmed_at: nil, confirmation_sent_at: "2013-03-05 13:15:53", unconfirmed_email: nil> 
1.9.3p385 :049 > u.confirm! 
    (0.1ms) BEGIN 
    (0.6ms) UPDATE `users` SET `confirmation_token` = NULL, `confirmed_at` = '2013-03-05 13:16:23', `updated_at` = '2013-03-05 13:16:23' WHERE `users`.`id` = 9 
    SQL (0.4ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:16:23', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.205031000 Z\nupdated_at: 2013-03-05 13:15:53.205031000 Z\nroles_mask: \nconfirmation_token: zNfBSVLJJ9nF4y5sanVU\nconfirmed_at: \nconfirmation_sent_at: 2013-03-05 13:15:53.204780000 Z\nunconfirmed_email: \nid: 9\n', NULL) 
    (25.4ms) COMMIT 
=> true 
1.9.3p385 :050 > u.versions.length 
    Version Load (0.5ms) SELECT `versions`.* FROM `versions` WHERE `versions`.`item_id` = 9 AND `versions`.`item_type` = 'User' ORDER BY created_at ASC, id ASC 
=> 2 
1.9.3p385 :051 > u.email = '[email protected]' 
=> "[email protected]" 
1.9.3p385 :052 > u.save 
    (0.1ms) BEGIN 
    User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`username` = BINARY 'bob' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    (0.2ms) UPDATE `users` SET `unconfirmed_email` = '[email protected]', `updated_at` = '2013-03-05 13:17:07' WHERE `users`.`id` = 9 
    SQL (0.2ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:17:07', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.205031000 Z\nupdated_at: 2013-03-05 13:16:23.677037000 Z\nroles_mask: \nconfirmation_token: \nconfirmed_at: 2013-03-05 13:16:23.674113000 Z\nconfirmation_sent_at: 2013-03-05 13:15:53.204780000 Z\nunconfirmed_email: \nid: 9\n', NULL) 
    User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`confirmation_token` = 'KJHQCtu74MqUSAdczu3Q' LIMIT 1 
    (11.2ms) UPDATE `users` SET `unconfirmed_email` = '[email protected]', `updated_at` = '2013-03-05 13:17:07', `confirmation_token` = 'KJHQCtu74MqUSAdczu3Q', `confirmation_sent_at` = '2013-03-05 13:17:07' WHERE `users`.`id` = 9 
    SQL (0.2ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:17:07', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.205031000 Z\nupdated_at: 2013-03-05 13:16:23.677037000 Z\nroles_mask: \nconfirmation_token: \nconfirmed_at: 2013-03-05 13:16:23.674113000 Z\nconfirmation_sent_at: 2013-03-05 13:15:53.204780000 Z\nunconfirmed_email: \nid: 9\n', NULL) 
    (0.5ms) COMMIT 
=> true 
1.9.3p385 :053 > u.email 
=> "[email protected]" 
1.9.3p385 :054 > u.unconfirmed_email 
=> "[email protected]" 
1.9.3p385 :055 > u.confirm! 
    (0.1ms) BEGIN 
    User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`username` = BINARY 'bob' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    (0.3ms) UPDATE `users` SET `confirmation_token` = NULL, `confirmed_at` = '2013-03-05 13:18:08', `email` = '[email protected]', `unconfirmed_email` = NULL, `updated_at` = '2013-03-05 13:18:08' WHERE `users`.`id` = 9 
    SQL (0.2ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:18:08', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.205031000 Z\nupdated_at: 2013-03-05 13:17:07.788127000 Z\nroles_mask: \nconfirmation_token: KJHQCtu74MqUSAdczu3Q\nconfirmed_at: 2013-03-05 13:16:23.674113000 Z\nconfirmation_sent_at: 2013-03-05 13:17:07.790567000 Z\nunconfirmed_email: [email protected]\nid: 9\n', NULL) 
    (15.4ms) COMMIT 
=> true 
1.9.3p385 :056 > u.email 
=> "[email protected]" 
1.9.3p385 :057 > u.versions.last.reify.save # revert to before the email confirm 
    User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 9 LIMIT 1 
    (0.1ms) BEGIN 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`username` = BINARY 'bob' AND `users`.`id` != 9) LIMIT 1 
    User Exists (0.2ms) SELECT 1 AS one FROM `users` WHERE (`users`.`email` = BINARY '[email protected]' AND `users`.`id` != 9) LIMIT 1 
    (0.3ms) UPDATE `users` SET `created_at` = '2013-03-05 13:15:53', `updated_at` = '2013-03-05 13:17:07', `confirmation_token` = 'KJHQCtu74MqUSAdczu3Q', `confirmed_at` = '2013-03-05 13:16:23', `confirmation_sent_at` = '2013-03-05 13:17:07', `unconfirmed_email` = '[email protected]' WHERE `users`.`id` = 9 
    SQL (0.2ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:20:13', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.000000000 Z\nupdated_at: 2013-03-05 13:18:08.000000000 Z\nroles_mask: \nconfirmation_token: \nconfirmed_at: 2013-03-05 13:18:08.000000000 Z\nconfirmation_sent_at: 2013-03-05 13:17:07.000000000 Z\nunconfirmed_email: \nid: 9\n', NULL) 
    User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`confirmation_token` = 'q9Y5ovWigLySxvz7PsaB' LIMIT 1 
    (0.2ms) UPDATE `users` SET `created_at` = '2013-03-05 13:15:53', `updated_at` = '2013-03-05 13:17:07', `confirmed_at` = '2013-03-05 13:16:23', `confirmation_sent_at` = '2013-03-05 13:20:13', `unconfirmed_email` = '[email protected]', `confirmation_token` = 'q9Y5ovWigLySxvz7PsaB' WHERE `users`.`id` = 9 
    SQL (17.4ms) INSERT INTO `versions` (`created_at`, `event`, `item_id`, `item_type`, `object`, `whodunnit`) VALUES ('2013-03-05 13:20:13', 'update', 9, 'User', '---\nusername: bob\nemail: [email protected]\nencrypted_password: !binary |-\n JDJhJDEwJDFCckFIMXlxZ0YzcWJna21wTVBsL3VFMFVZNzkyYUI4ZnZZS0xr\n c01ueVFzbjdzTS9kWTRP\nreset_password_token: \nreset_password_sent_at: \nremember_created_at: \nsign_in_count: 0\ncurrent_sign_in_at: \nlast_sign_in_at: \ncurrent_sign_in_ip: \nlast_sign_in_ip: \ncreated_at: 2013-03-05 13:15:53.000000000 Z\nupdated_at: 2013-03-05 13:18:08.000000000 Z\nroles_mask: \nconfirmation_token: \nconfirmed_at: 2013-03-05 13:18:08.000000000 Z\nconfirmation_sent_at: 2013-03-05 13:17:07.000000000 Z\nunconfirmed_email: \nid: 9\n', NULL) 
    (7.0ms) COMMIT 
=> true 

現在,我們已經恢復了用戶狀態的新的電子郵件確認前:我可以在幾行軌控制檯下方說明問題

1.9.3p385 :059 > u = User.where(username: 'bob').first 
    User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`username` = 'bob' LIMIT 1 
=> #<User id: 9, username: "bob", email: "[email protected]", encrypted_password: "$2a$10$1BrAH1yqgF3qbgkmpMPl/uE0UY792aB8fvYKLksMnyQs...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2013-03-05 13:15:53", updated_at: "2013-03-05 13:17:07", roles_mask: nil, confirmation_token: "q9Y5ovWigLySxvz7PsaB", confirmed_at: "2013-03-05 13:16:23", confirmation_sent_at: "2013-03-05 13:20:13", unconfirmed_email: "[email protected]"> 
1.9.3p385 :060 > u.email 
=> "[email protected]" 
1.9.3p385 :061 > u.unconfirmed_email 
=> "[email protected]" 

正如我們所看到的,這不是用戶之前的狀態。我想這是因爲Devise檢測到電子郵件發生變化,並且新電子郵件被設置爲未經確認的電子郵件。無論如何,只有在恢復到此對象的以前版本時,我纔可以繞過這一點?

另外,我注意到Devise爲單個電子郵件更新執行2 USER users語句(第一個是第二個子集)。任何理由爲此,有沒有修復?它爲用戶添加了額外的不必要的版本記錄。

回答

0

我花更多的時間與這兩個設計和paper_trail,我相信我已經找到了如何手動更改電子郵件和跳過(重新)確認的選項搞混。

# skipping the initial confirmation 
user = User.new email: '[email protected]', password: 'secret', username: 'foo' 
user.skip_confirmation! 
user.save 
user.versions.length # => 1 

# skip the reconfirmation 
user.email = '[email protected]' 
user.skip_reconfirmation! 
user.save 
user.versions.length # => 2 

# revert 
reverted_user = user.versions.last.reify 
reverted_user.live? # => false 
reverted_user.skip_reconfirmation! 
reverted_user.save 
reverted_user.live? # => true 
reverted_user.email # => "[email protected]" 

skip_reconfirmation!使得直接保存設置email領域,而不是將其設置爲unconfirmed_email

編輯:經過更多的工作,我很困惑又一次什麼paper_trail做:

let(:user) { User.new(username: 'bob', email: '[email protected]', password: 'secret101') } 
it "can revert to a previous version" do 
    user.save # version 1 (unconfirmed) 

    user.confirm! # version 2 (confirmed) 

    user.email.should eq '[email protected]' 
    user.unconfirmed_email.should be_nil 

    user.update_attributes email: '[email protected]' # version 3, 4 (un-reconfirmed) 
    user.versions.should have(4).items 

    user.email.should eq '[email protected]' 
    user.unconfirmed_email.should eq '[email protected]' 

    user.confirm! # version 5 (reconfirmed) 
    user.versions.should have(5).items 

    user.email.should eq '[email protected]' 
    user.unconfirmed_email.should be_nil 

    # revert to the first confirmed user 
    reverted_user = user.versions[2].reify 
    reverted_user.email.should eq '[email protected]' 
    reverted_user.unconfirmed_email.should be_nil 
    reverted_user.should be_confirmed 
    reverted_user.should_not be_live 
    reverted_user.skip_reconfirmation! 
    reverted_user.save!.should be_true 
    reverted_user.should be_live # FAILS 

    live_user = User.where(username: 'bob').first 
    live_user.should be_live 
    live_user.should be_confirmed 
    live_user.email.should eq '[email protected]' 
    live_user.unconfirmed_email.should be_nil 

    user.email.should eq '[email protected]' # => passes 
    user.should_not be_live # => FAILS 
end 

我不明白爲什麼2項與註釋「失敗」是失敗的規範