I'm currently working on a model for a User
that has_many :addresses
; These addresses form a small address book from which a user can choose shipping and mailing addresses.
My question is, what's the the best way for me to tag one of the Address
objects in the has_many
relationship as the default address?
One way (I think I've got this right) would be to maintain this relationship:
class User < ActiveRecord::Base
has_many :addresses, :dependent => :destroy
has_one :default_address, :class_name => "Address"
class Address < ActiveRecord::Base
belongs_to :user
belo开发者_StackOverflowngs_to :user, :foreign_key :default_address_id
but I know that's sloppy, as I'll have two links between my default address and my user.
Should I be setting a default boolean in address, and grabbing the default using scope
? (This adds an extra validation, as I don't want multiple default addresses... hmm.)
I figure this must come up fairly often in applications with address management, so figured I'd lay out my ideas and just ask. Any recommendations on best practices would be much appreciated.
I'd add a 'is_default' flag to Addresses. Then you'll need a validation in the Addresses that is something like:
validates_uniqueness_of :is_default, :scope => :user_id, :unless => Proc.new { |address| address.is_default == 0 }
This will ensure you only get one default address but will allow for as many non-default addresses as you want.
If it was me, I'd say the foreign key belongs on the User, with a boolean method on the address to figure out if its the default address (assuming you'll need that in your app):
class User < ActiveRecord::Base
has_many :addresses, :dependent => :destroy
belongs_to :default_address, :class_name => "Address"
end
class Address < ActiveRecord::Base
belongs_to :user
def default_address?
user.default_address == self
end
end
Another potential avenue is to give the address a boolean flag to indicate that its a default address and use an accessor in the User model to get to it:
class User
has_many :addresses
def default_address
addresses.select(&:default_address?) #overly simple implementation
end
end
Your app will need to handle the logic to ensure there's only one default address using the second arrangement.
精彩评论