acts_as_relatable
Installation
(This gem has only been tested with Rails 3 for the moment, compatibility with Rails 3.1 is coming soon)
Gem installation :
gem install acts_as_relatable
Or you can put it in your Gemfile :
gem "acts_as_relatable", "~> 0.0.5"
and then run :
bundle install
You’ll then need to run the migration generator for the Relationship model :
r generate acts_as_relatable:migration
Followed by :
rake db:migrate
Usage
# Model definition
class Tool < ActiveRecord::Base
acts_as_relatable :product
end
class Product < ActiveRecord::Base
acts_as_relatable :recipe
end
class Recipe < ActiveRecord::Base
acts_as_relatable :product, :tool
end
# Create some entries
@bread = Product.create(:name => "Bread")
@butter = Product.create(:name => "Butter")
@pancake = Recipe.create(:name => "Pancakes")
@mixer = Tool.create(:name => "Mixer")
Creating relationships
@butter.relates_to!(@pancake) # #<ActsAsRelatable::Relationship id: 2, relator_id: 2, relator_type: "Product", related_id: 1, related_type: "Recipe">
@pancake.relates_to!(@mixer) # #<ActsAsRelatable::Relationship id: 3, relator_id: 1, relator_type: "Recipe", related_id: 1, related_type: "Tool">
@bread.relates_to!(@butter) # #<ActsAsRelatable::Relationship id: 4, relator_id: 1, relator_type: "Product", related_id: 2, related_type: "Product">
# By default, relationships are both-sided, it means that on the first line above,
# @butter is related to @pancake, but @pancake is also related to @butter.
# If you don't want/need this behaviour, you can pass false as a second argument
# to the relates_to! instance method :
@butter.relates_to!(@pancake, false)
# You can also create relationships with the ActsAsRelatable::Relationship class method
ActsAsRelatable::Relationship.make_between(@butter, @pancake) # Passing false as a third argument make it "one sided"
Fetching relationships
@butter. # [#<Recipe id: 1, name: "Pancakes">]
@butter. # [#<Product id: 1, name: "Bread"]
@butter. # {:recipes=>[#<Recipe id: 1, name: "Pancakes">], :products=>[#<Product id: 1, name: "Bread">]}
@pancake. # {:tools=>[#<Tool id: 1, name: "Mixer">], :products=>[#<Product id: 2, name: "Butter">]}
#Testing relationships
@butter. @bread # true
@bread. @pancake # false
#Destroying relationships (This instance method destroys both relationships if it's a both-sided one)
@butter.destroy_relation_with @pancake
Getting Relatable types
@pancake.relatable_types # [:product, :tool]
Configuration
To create the acts_as_relatable config file, open a shell and run :
r g acts_as_relatable:config
It will create a file called acts_as_relatable.rb in config/initializers
Relationship Shortcut
By default, the Relationship model is accessible with :
ActsAsRelatable::Relationship
ActsAsRelatable::Relationship.count
If you want to access it directly with
Relationship
Relationship.first
Just uncomment this line in the config file (see Configuration section above to see how to generate it)
Relationship = ActsAsRelatable::Relationship
Relationship model extension
You can add class/instance methods to the ActsAsRelatable::Relationship model by adding a module in your project. Here is how to do it :
Add a new file named relationship_extension.rb in your app/models directory.
Let’s call this module RelationshipExtension. The file may look like :
module RelationshipExtension
def self.included(klass)
klass.extend(ClassMethods).relate
end
module ClassMethods
def relate
include RelationshipExtension::InstanceMethods
end
end
module InstanceMethods
def to_s
"#{relator.class} #{relator.id} is related with #{.class} #{.id}"
end
end
end
Generate the config file (see Configuration section above to see how to generate it)
Open this file and uncomment this line :
ActsAsRelatable::Relationship.send(:include, RelationshipExtension)
I define a to_s instance method in this example. It is now a part of the ActsAsRelatable::Relationship model and you can use it like that :
ActsAsRelatable::Relationship.first.to_s
it will return :
"Product 1 is related with Recipe 1"
Contributing to acts_as_relatable
-
Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet
-
Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it
-
Fork the project
-
Start a feature/bugfix branch
-
Commit and push until you are happy with your contribution
-
Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
TODOS
-
Rails 3.1 compatibility
-
Add a make_between method in Relationship model
-
Improve README
-
Specs for generators
Copyright
Copyright © 2011 Malamitsas. See LICENSE.txt for further details.