我正在尝试考虑允许用户在不创建帐户的情况下创建数据库对象的最佳方法,然后在他们决定注册时将这些对象与用户的帐户相关联。我将描述一个示例应用程序,我希望它如何运行,以及我想出的方法。我正在寻找对我的方法的批评/改进,或者是你们中的一个人,我的程序员伙伴们想要的更好的方法。
示例应用程序
假设我们有一个名为Suggestion Box的 Rails 应用程序。此应用程序允许用户访问该站点并输入建议。ASuggestion
需要描述和电子邮件地址。用户无需登录。以下是型号:
应用程序/模型/建议.rb
class Suggestion < ActiveRecord::Base
# == DB Columns
# id :integer
# user_id :integer
# description :text
# email :string
belongs_to :user
validates :description, :email, :presence => true
end
应用程序/模型/user.rb
class User < ActiveRecored::Base
# == DB Columns
# id :integer
# name :string
# email :string
has_many :suggestions
validates :name, :email, :presence => true
end
用例
Frank 来到 Suggestion Box 应用程序并输入一个建议。第二天弗兰克又进来了。如果我们向 Rails 控制台询问所有建议,我们将得到:
# rails console
Suggestion.all
=> [#<Suggestion id: 1, user_id: nil, email: "frank@example.com", description: "Don't worry">,
#<Suggestion id: 2, user_id: nil, email: "frank@example.com", description: "Be happy">]
第三天,弗兰克决定硬着头皮注册一个帐户。然后他提出另一个建议。此时,如果我们向控制台询问User
对象,我们会得到 Frank:
# rails console
User.all
=> [#<User id: 1, name: "Frank", email: "frank@example.com" >]
如果我们询问弗兰克的建议,我们会得到所有 3 条建议:
# rails console
frank = User.last
=> [#<User id: 1, name: "Frank", email: "frank@example.com" >
frank.suggestions
=> #<ActiveRecord::Associations::CollectionProxy [#<Suggestion id: 1, user_id: nil, email: "frank@example.com", description: "Don't worry">,
#<Suggestion id: 2, user_id: nil, email: "frank@example.com", description: "Be happy">,
#<Suggestion id: 3, user_id: nil, email: "frank@example.com", description: "Don't worry be happy now!">]
现在我们如何在弗兰克和他过去的建议之间建立这种联系?
方法
#1 饼干
当未登录的用户提交会话时,我可以在 cookie 中存储有关创建的建议的指示符。然后,当他们注册时,我可以使用此信息来查找建议并将其分配给用户。
我不太喜欢这种方法,因为当用户访问多个设备时它会崩溃。
#2 创建回调后
当用户注册时,我可以运行如下所示的创建后回调:
应用程序/models.user.rb
class User < ActiveRecored::Base
...
after_create :assign_suggestions
def assign_suggestions
suggestions = Suggestion.where(:user_id => nil, :email => self.email)
suggestions.each do |s|
s.user = self
s.save
end
end
end
我真的很喜欢这种方法,但有一个主要缺点。如果 Frank 在未登录时创建第四个建议,则不会将其添加到他的用户对象中。Suggestion
为了解决这个问题,我可以在可以检查匹配电子邮件的类上编写一个回调。
应用程序/模型/建议.rb
class Suggestion < ActiveRecord::Base
...
after_create :assign_users
def assign_users
if self.user.present?
user = User.where(:email => self.email).first
if user
self.user = user
end
end
end
end
This is pretty good but if Frank creates a suggestion with a different email address (which could happen, I have many) then the suggestion will not be connected to Frank's user object.
Question
What do you guys think of Approach #2? (good or bad) Is there another trick on top of this I could use to connect Frank to suggestions he makes with other email addresses? Can you think of a different approach that would work better than mine?
Thanks for the advice!