
on-the-fly associations OR creating custom association accessor/setter methods
Reported by Daniel Parker | March 24th, 2008 @ 02:19 PM
Associations are always set statically and associated with the model class. This is not always the way the developer would like it to work. Many times I find myself wishing I could create accessor methods that would access a subset of an association.
Currently there are a couple ways to do this: 1) Create another association with some more finder options, or 2) Create an accessor method to grab the whole set but filter out the ones I don't want. Neither of those are satisfactory -- the first because it's not really a separate association, it's the same association with a more precise scope; the second because it grabs unnecessary objects from the database.
Example: Person model.. I need a phone_numbers association, but I need to be able to access cell numbers, work numbers, home numbers or fax numbers, separately. In reality, there may be more types, and I need to be able to grab whichever type with the option :context => 'cell', etc. A syntax such as Person.phone_numbers.find(:context => 'cell') would be satisfactory, but that method must return an association_collection, with the finder options all ready to apply to new objects I might build or << into that collection.
I propose separating the association definitions from the accessor/setter methods, and opening up the association set to be a little more publicly usable. Attached is a quick working "plugin" -- just require it after DataMapper is loaded, and the following code should work:
class Email < DataMapper::Base
property :person_id, :integer
property :context, :string
end
class Person < DataMapper::Base
def phone_numbers
@phone_numbers || begin
@phone_numbers = associated_records(:class => :PhoneNumber, :foreign_key => :person_id)
def @phone_numbers.[](k)
@phone_numbers_by_context ||= {}
@phone_numbers_by_context[k] ||= @items ? @items.reject {|e| e.context != k} : find(:context=>k)
end
@phone_numbers
end
end
end
p = Person.first
p.phone_numbers['cell'] # does a sql request for just the :context => 'cell' records, saves them,
# but not into the whole association set.
p.phone_numbers['home'] # does another sql request
p.phone_numbers # sql request for all associated records
p.phone_numbers['work'] # since all records are loaded, just filters them in ruby.
I'm not hoping my code is used, I'm just hoping to get my case across -- I believe it'd allow for much easier use of associations.
Comments and changes to this ticket
-
Dan Kubb (dkubb) April 15th, 2008 @ 03:36 AM
- Milestone cleared.
-
Sam Smoot April 27th, 2008 @ 10:49 PM
- Assigned user set to David Leal
- State changed from new to open
I think I get the point... this is what we're going for basically with the finders returning the Collection class directly. So I believe this is basically a done deal. Just the same, we'll make sure and spec the use cases before marking this resolved.
-
Sam Smoot June 2nd, 2008 @ 04:56 PM
- Milestone cleared.
-
Dan Kubb (dkubb) December 4th, 2008 @ 03:21 AM
- Milestone cleared.
- State changed from open to resolved
- Assigned user changed from David Leal to Dan Kubb (dkubb)
I can confirm that this functionality exists in dm-core, and has existed since probably early summer. Marking this ticket as resolved.
-
Dan Kubb (dkubb) December 4th, 2008 @ 03:22 AM
- Milestone cleared.
Please Sign in or create a free account to add a new ticket.
With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »