Folks,
I have a need to normalize some DB tables, and I'm having difficulty working out how ActiveRecord models should handle this need. Any advice would be greatly appreciated.
The user model was previously very simple, which allowed for simple data binding to the view.
class User < ActiveRecord::Base attr_accessor :password, :password_confirmation
attr_accessible :name, :email_address, :password, :password_confirmation # ... end
<% remote_form_for :user, :url => { :controller => :user, :action => :add } do |u| %> <label>Display name:</label><%= u.text_field :name %> <label>Email address:</label><%= u.text_field :email %> <label>Password:</label><%= u.password_field :password %> <label>Confirm password:</label><%= u.password_field :password_confirmation %> <input type='submit' value='Create account'></input> <% end %>
I'm now adding the ability for a user to invite another user to join the site (by entering their email address). The 2 approaches I considered were: 1. Create an invitation model that joins 2 users. All user fields except for email address would have to be nullable, so my model validation would be non-existent and this whole direction feels ugly. 2. Create an invitation model that joins a user and an email address. The user and invitation models now both have an email address, and both for performance and to maintain a clean data model the email address should be normalized into its own model.
My challenge with option 2 is that, while the email address is still logically a part of the user model and needs to be data bound to the view in the same way as before, this requires a bit of mucking around and I'm not sure if there is an easier way. My approach looks like this:
class Email < ActiveRecord::Base attr_accessible :email_address # ... end class User < ActiveRecord::Base belongs_to: email attr_accessor :email_address, :password, :password_confirmation
attr_accessible :name, :email_address, :password, :password_confirmation
# Move email_address between accessor (needed for data binding) and email instance
before_validation_on_create :create_email_instance_from_email_address_attr after_find :set_email_address_attr_from_email_instance
def validate # Validate that no user (except for this one, in case of update) has this email address, # as validate_uniqueness_of cannot be used end
# ... end
belongs_to is normally used to link 2 logically separate models, whereas here the 2 model design is purely a result of normalization from multiple tables needing to store email addresses. Is there a better way?
Any insight is greatly appreciated.
Regards, Chris