Created
March 9, 2012 10:51
-
-
Save troyk/2006057 to your computer and use it in GitHub Desktop.
Neat little STI association trick, works with to_json but finder include needs some love
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Objective: An association using STI should only query the db once for the base class | |
| class Contact < ActiveRecord::Base | |
| has_many :info, :class_name=>'::Contact::ContactInfo' | |
| has_many :phones, :class_name=>'::Contact::Phone' | |
| has_many :emails, :class_name=>'::Contact::Email' | |
| has_many :addresses, :class_name=>'::Contact::Address' | |
| # load all info's thorugh info | |
| # this is possible due to how associations are mixed into the class via a module | |
| def info | |
| unless info_assoc = @association_cache[:info] | |
| info_assoc = self.association(:info) | |
| a = {:phones => [], :emails => [], :addresses => []} | |
| info_assoc.load_target.each do |info| | |
| a[:phones].push(info) and next if info.is_a?(::Contact::Phone) | |
| a[:emails].push(info) and next if info.is_a?(::Contact::Email) | |
| a[:addresses].push(info) and next if info.is_a?(::Contact::Address) | |
| end | |
| a.each { |assoc_name, records| self.association(assoc_name).target = records } | |
| end | |
| info_assoc | |
| end | |
| def phones; self.info; super; end | |
| def emails; self.info; super; end | |
| def addresses; self.info; super; end | |
| class ContactInfo < ActiveRecord::Base | |
| set_table_name "contacts_info" | |
| end | |
| class Email < ContactInfo | |
| end | |
| class Phone < ContactInfo | |
| end | |
| class Address < ContactInfo | |
| end | |
| end | |
| # to_json works like a charm | |
| >> Contact.first.to_json(:include=>[:phones,:emails,:addresses]) | |
| D, [2012-03-09T02:50:21.378127 #47368] DEBUG -- : Contact Load (0.6ms) SELECT "contacts".* FROM "contacts" LIMIT 1 | |
| D, [2012-03-09T02:50:21.380086 #47368] DEBUG -- : Contact::ContactInfo Load (0.5ms) SELECT "contacts_info".* FROM "contacts_info" WHERE "contacts_info"."contact_id" = 1 | |
| # finder includes, meh... | |
| >> Contact.first(:include=>[:phones,:emails,:addresses]).to_json(:include=>[:phones,:emails,:addresses]) | |
| D, [2012-03-09T02:46:09.721232 #47368] DEBUG -- : Contact Load (0.7ms) SELECT "contacts".* FROM "contacts" LIMIT 1 | |
| D, [2012-03-09T02:46:09.722783 #47368] DEBUG -- : Contact::Phone Load (0.6ms) SELECT "contacts_info".* FROM "contacts_info" WHERE "contacts_info"."type" IN ('Contact::Phone') AND "contacts_info"."contact_id" IN (1) | |
| D, [2012-03-09T02:46:09.730487 #47368] DEBUG -- : Contact::Email Load (0.4ms) SELECT "contacts_info".* FROM "contacts_info" WHERE "contacts_info"."type" IN ('Contact::Email') AND "contacts_info"."contact_id" IN (1) | |
| D, [2012-03-09T02:46:09.731696 #47368] DEBUG -- : Contact::Address Load (0.4ms) SELECT "contacts_info".* FROM "contacts_info" WHERE "contacts_info"."type" IN ('Contact::Address') AND "contacts_info"."contact_id" IN (1) | |
| D, [2012-03-09T02:46:09.732826 #47368] DEBUG -- : Contact::ContactInfo Load (0.3ms) SELECT "contacts_info".* FROM "contacts_info" WHERE "contacts_info"."contact_id" = 1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment