如果这些条目是在用户帐户之前创建的,那么如何使数据库条目粘贴到用户的帐户

时间:2013-05-11 23:53:26

标签: ruby-on-rails database callback user-accounts

我正在尝试考虑允许用户在不创建帐户的情况下创建数据库对象的最佳方法,然后在他们决定注册时将这些对象与用户的帐户相关联。我将描述一个示例应用程序,我希望它如何表现,以及我提出的方法。我正在寻找对我的方法的批评/改进,或者是我和你们其中一位程序员的更好方法。

示例应用程序

假设我们有一个名为意见箱的Rails应用程序。此应用程序允许用户访问该站点并输入建议。 Suggestion需要说明和电子邮件地址。用户无需登录。以下是型号:

应用程序/模型/ 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

应用程序/模型/ 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 Cookies

当未登录的用户提交会话时,我可以在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类上编写一个可以检查匹配电子邮件的回调。

应用程序/模型/ 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有什么看法? (好的或坏的)除此之外还有另一个技巧我可以用Frank将他与其他电子邮件地址建议联系起来吗?你能想到一种比我更好的方法吗?

感谢您的建议!

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试一次解决两个方案:分配用户是您的主要问题,并将多个电子邮件地址处理到一个帐户。

email address字段在两个模型中重复。最初我建议保留User中的电子邮件地址,并创建匿名(无名称)User,然后从那里构建。这将改变您的Suggestion创建过程,因为您将立即关联到User记录。由于您正在尝试处理多个电子邮件问题,我建议将电子邮件地址分解为单独的模型:

class EmailAddress << ActiveRecord::Base
  # == DB Columns
  # id           :integer
  # user_id      :integer
  # email        :string

  belongs_to :user
  has_many :suggestions
  validates :email, presence :true
end

相应地更改其他模型:

class Suggestion << ActiveRecord::Base
  ...

  belongs_to :email
end

class User << ActiveRecord::Base
  ...

  has_many :email
end

您可以选择立即创建User或将其推迟到实际注册帐户(我会推迟)。

至于某人在未注册时创建建议并且必须在事后进行该关联的情况。这个结构使这更容易,但我实际上不允许这个。我会告诉用户类似this email address is already registered, please sign in to submit your suggestion的内容。假设你想确保人们不会错误地以其他人的名义创建建议。