0

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

示例应用程序

假设我们有一个名为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!

4

1 回答 1

0

It seems you're trying to solve two scenarios at once: assigning the user is you main question, and handling multiple email addresses to one account.

The email address field is duplicated in two models. Initially I would have suggested leave the email address in User, and create anonymous (no name) Users and then build from there. That would change your Suggestion create process since you would be associating to the User record immediately. Since you're trying to handle the multiple email question, I would suggest breaking the email address out into a separate model:

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

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

change the other models accordingly:

class Suggestion << ActiveRecord::Base
  ...

  belongs_to :email
end

class User << ActiveRecord::Base
  ...

  has_many :email
end

It would be your option to either create User immediately or defer it until they actually sign up for an account (I would defer).

As for the scenario of someone creating a suggestion when not signed up and having to make that association after the fact. This structure makes that easier BUT I would actually not allow that personally. I would inform the user something like this email address is already registered, please sign in to submit your suggestion. Assuming you want to make sure that people aren't falsely creating suggestions under other people's names.

于 2013-05-12T14:25:39.077 回答