Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to make database entries stick to a User's account if those entries were created before the User account was
    primarykey
    data
    text
    <p>I'm trying to think of the best way to allow users to create database objects without creating an account but then associating those objects with a user's account when they decide to sign up. I will describe an example application, how I would like it to behave, and the approaches I have come up with. I am looking for criticisms/enhancements to my approaches or a better approach purposed by one of you, my fellow programmers. </p> <h1>Example Application</h1> <p>Let's say we have a Rails application called <strong>Suggestion Box</strong>. This application allows users to visit the site and enter a suggestion. A <code>Suggestion</code> requires a description and an email address. The user does not need to be logged in. Here are the models:</p> <p><em>app/models/suggestion.rb</em></p> <pre><code>class Suggestion &lt; ActiveRecord::Base # == DB Columns # id :integer # user_id :integer # description :text # email :string belongs_to :user validates :description, :email, :presence =&gt; true end </code></pre> <p><em>app/models/user.rb</em></p> <pre><code>class User &lt; ActiveRecored::Base # == DB Columns # id :integer # name :string # email :string has_many :suggestions validates :name, :email, :presence =&gt; true end </code></pre> <h1>Use Case</h1> <p>Frank comes to the Suggestion Box application and enters in a suggestion. The next day Frank enters in another. If we ask the Rails console for all of suggestions we will get this:</p> <pre><code># rails console Suggestion.all =&gt; [#&lt;Suggestion id: 1, user_id: nil, email: "frank@example.com", description: "Don't worry"&gt;, #&lt;Suggestion id: 2, user_id: nil, email: "frank@example.com", description: "Be happy"&gt;] </code></pre> <p>On the third day Frank decides to bite the bullet and sign up for an account. He then creates another suggestion. At this point if we ask the console for <code>User</code> objects we get Frank:</p> <pre><code># rails console User.all =&gt; [#&lt;User id: 1, name: "Frank", email: "frank@example.com" &gt;] </code></pre> <p>If we ask for Frank's suggestions we get all 3 suggestions:</p> <pre><code># rails console frank = User.last =&gt; [#&lt;User id: 1, name: "Frank", email: "frank@example.com" &gt; frank.suggestions =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Suggestion id: 1, user_id: nil, email: "frank@example.com", description: "Don't worry"&gt;, #&lt;Suggestion id: 2, user_id: nil, email: "frank@example.com", description: "Be happy"&gt;, #&lt;Suggestion id: 3, user_id: nil, email: "frank@example.com", description: "Don't worry be happy now!"&gt;] </code></pre> <p>Now how do we make this connection between Frank and his past suggestions automatic?</p> <h1>Approaches</h1> <h3>#1 Cookies</h3> <p>When a non logged in user submits a session I could store an indicator in a cookie about the created suggestions. Then when they sign up I could use this info to find the suggestions and assign them to the user. </p> <p>I don't really like this approach because it breaks down when the user accesses more than one device. </p> <h3>#2 After Create Callback</h3> <p>When a user signs up I could run an after create callback that would look like this:</p> <p><em>app/models.user.rb</em></p> <pre><code>class User &lt; ActiveRecored::Base ... after_create :assign_suggestions def assign_suggestions suggestions = Suggestion.where(:user_id =&gt; nil, :email =&gt; self.email) suggestions.each do |s| s.user = self s.save end end end </code></pre> <p>I really like this approach but there is one major downside. If Frank creates a fourth suggestion when not logged in it will not be added to his user object. To fix this I could write a callback on the <code>Suggestion</code> class that could check for matching emails.</p> <p><em>app/models/suggestion.rb</em></p> <pre><code>class Suggestion &lt; ActiveRecord::Base ... after_create :assign_users def assign_users if self.user.present? user = User.where(:email =&gt; self.email).first if user self.user = user end end end end </code></pre> <p>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.</p> <h1>Question</h1> <p>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?</p> <p>Thanks for the advice!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload