tests are nice
[has_many_polymorphs.git] / README
blobc1d0e5d7921d1d5ab12bac56463839ab0f99bd9b
2 has_many_polymorphs
4 An ActiveRecord plugin for defining self-referential polymorphic associations.
6 == License
8 Copyright 2007 Cloudburst, LLC. Licensed under the AFL 3. See the included LICENSE file. 
10 == Description
12 This plugin gives you the ability to define easy-to-use self-referential polymorphic associations with full array-like behavior in your models. It is an extension of <tt>has_many :through</tt>.
14 “Polymorphic” means an association can freely point to any of several unrelated model classes, instead of being tied to one particular class.
16 == Features
18 * self-references
19 * double-sided polymorphism
20 * efficient, merged association SELECT
21 * STI support
22 * namespace support
23 * automatic individual and reverse associations
25 And a generator for a tagging system, a common use case.
27 == Requirements
29 * Rails 1.2.3 or greater
31 = Usage
33 == Installation
35 To install the Rails plugin, run:
36   script/plugin install svn://rubyforge.org/var/svn/polymorphs/has_many_polymorphs
38 There's also a gem version. To install it instead, run: 
39   sudo gem install has_many_polymorphs
40   
41 If you are using the gem, make sure to add <tt>require 'has_many_polymorphs'</tt> to <tt>environment.rb</tt>, before Rails::Initializer block.
43 == Configuration
45 Setup the parent model as so:
47   class Petfood < ActiveRecord::Base
48     has_many_polymorphs :eaters, :from => [:dogs, :cats, :birds]
49   end
51 The join model:
53   class EatersPetfood < ActiveRecord::Base
54     belongs_to :petfood
55     belongs_to :eater, :polymorphic => true
56   end
58 One of the child models:
60   class Dog < ActiveRecord::Base
61     # nothing
62   end
64 See ActiveRecord::Associations::PolymorphicClassMethods for more configuration options.
66 == Helper methods example
68   petfood = Petfood.find(1)
69   petfood.eaters.map(&:class) # => [Dog, Cat, Cat, Bird]
70   
71   petfood.eaters.push(Cat.create)
72   petfood.eaters << Cat.create
73   petfood.cats.size # => 4
74   petfood.eaters.size # => 6
75   
76   petfood.eaters.delete(petfood.dogs[0])
77   petfood.dogs.size # => 0
78   petfood.eaters.size # => 5
80   # works both ways
81   petfood.eaters[0].petfoods.include?(petfood) # => true
83 See ActiveRecord::Associations::PolymorphicAssociation for more helper method details.
85 = Extras
87 == Double-sided polymorphism
89 Double-sided relationships are defined on the join model:
91   class Devouring < ActiveRecord::Base
92     belongs_to :eater, :polymorphic => true
93     belongs_to :eaten, :polymorphic => true
94   
95     acts_as_double_polymorphic_join(
96       :eaters =>[:dogs, :cats], 
97       :eatens => [:cats, :birds]
98     )       
99   end
100   
101 Now, dogs and cats can eat birds and cats. Birds can't eat anything (they aren't <tt>eaters</tt>) and dogs can't be eaten by anything (since they aren't <tt>eatens</tt>). The keys stand for what the models are, not what they do. 
103 In this case, each eater/eaten relationship is called a Devouring.
105 See ActiveRecord::Associations::PolymorphicClassMethods for more.
107 == Tagging generator
109 Has_many_polymorphs includes a tagging system generator.
111   ./script/generate tagging TaggableModel1 TaggableModel2 [..]
113 You can use the flag <tt>--skip-migration</tt> (to avoid generating a migration, for example, if you are converting from <tt>acts_as_taggable)</tt>, as well as the flag <tt>--self-referential</tt> (if you want tags to be able to tag tags).
115 Tests will be generated, but will not work unless you have at least 2 fixture entries for the first two taggable models. Their ids must be 1 and 2.
117 == Troubleshooting
119 Some debugging tools are available in <tt>lib/has_many_polymorphs/debugging_tools.rb</tt>.
121 If you are having trouble, think very carefully about how your model classes, key columns, and table names relate. You may have to explicitly specify options on your join model such as <tt>:class_name</tt>, <tt>:foreign_key</tt>, or <tt>:as</tt>. The included tests are a good place to look for examples.
123 Note that because of the way Rails reloads model classes, the plugin can sometimes bog down your development server. Set <tt>config.cache_classes = true</tt> in <tt>config/environments/development.rb</tt> to avoid this. 
125 == Further resources
127 * http://blog.evanweaver.com/pages/code#polymorphs
128 * http://rubyforge.org/forum/forum.php?forum_id=8117