【发布时间】:2013-05-11 23:53:25
【问题描述】:
我正在尝试考虑一种最佳方式,即允许用户在不创建帐户的情况下创建数据库对象,然后在他们决定注册时将这些对象与用户的帐户相关联。我将描述一个示例应用程序,我希望它如何运行,以及我想出的方法。我正在寻找对我的方法的批评/改进,或者是你们中的一个人,我的程序员伙伴们想要的更好的方法。
示例应用程序
假设我们有一个名为 Suggestion Box 的 Rails 应用程序。此应用程序允许用户访问该站点并输入建议。 Suggestion 需要描述和电子邮件地址。用户无需登录。以下是模型:
app/models/suggestion.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
app/models/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" >]
如果我们询问 Frank 的建议,我们会得到全部 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 Cookies
当未登录的用户提交会话时,我可以在 cookie 中存储有关创建的建议的指示符。然后,当他们注册时,我可以使用此信息来查找建议并将其分配给用户。
我不太喜欢这种方法,因为当用户访问多个设备时它会崩溃。
#2 创建回调后
当用户注册时,我可以运行如下所示的创建后回调:
app/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 类上编写一个回调来检查匹配的电子邮件。
app/models/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
这很好,但如果 Frank 使用不同的电子邮件地址创建建议(可能会发生,我有很多),那么建议将不会连接到 Frank 的用户对象。
问题
你们如何看待方法 #2? (好或坏)除此之外,我是否可以使用另一个技巧将弗兰克与他通过其他电子邮件地址提出的建议联系起来?你能想出比我更好的方法吗?
感谢您的建议!
【问题讨论】:
标签: ruby-on-rails database callback user-accounts