JoinCollection
Join an array of mongoid docs with target objects by specified relation and delegation fields
Installation
Add this line to your application's Gemfile:
gem 'join_collection'
And then execute:
$ bundle
Or install it yourself as:
$ gem install join_collection
Usage
Initialize a JoinCollection object
The class JoinCollection itself is a wrapper around an array of mongoid docs, so to initialize it, simply put
user_collection = JoinCollection.new(users) # where users is an array of mongoid docs
We will call what we put inside the initilizer the source objects.
Specifiy parameters to join docs
To use any of the join_*
functions, make sure you provide the following parameters.
- The 1st parameter is the
target_name
, which is used as the prefix for the delegation fields. - The 2nd parameter is the
target_class
, which is used to query target objects. - The 3rd parameter is the
options
, which is not optional and it must be a hash containing a:relation
key and a:delegation
key.
- The key
:relation
points to another hash, which specifies the foreign key to primary key for the type of join relation. - The key
:delegation
also points to a hash, which specifies the:fields
of the target object to be delegated to the doc in the source objects. In a has_many relation, you can also privide a:if
conditional block to specify which target object to delegate if there are many target objects.
Examples
Join docs with belongs_to
relation
Assume we have a user belongs_to site
relationship, and the Site class has the field url
.
user_collection = JoinCollection.new(users)
user_collection.join_to(:site, Site, :relation => {:site_id => :id}, :delegation => {:fields => [:url]})
After this, all the source objects, the users, in the user_collection will have the field site_url
user_collection.source_objects.first.site_url # => "http://..."
Join docs with has_one
relation
Assume we have a user has_one profile
relationship, and the Profile class has the field twitter
.
user_collection = JoinCollection.new(users)
user_collection.join_one(:profile, Profile, :relation => {:user_id => :id}, :delegation => {:fields => [:twitter]})
After this, all the source objects, the users, in the user_collection will have the field profile_twitter
user_collection.source_objects.first.profile_twitter # => "https://twitter.com/..."
Join docs with has_many
relation
Assume we have a user has_many contacts
relationship, and the Contact class has the field phone
.
user_collection = JoinCollection.new(users)
user_collection.join_many(:contacts, Contact, :relation => {:user_id => :id},
:delegation => {:if => lambda { |x| x.is_active? }, :fields => [:phone]})
After this, all the source objects, the users, in the user_collection will have the field contact_phone
user_collection.source_objects.first.contact_phone # => "0987-654-321"
Notes
If you specify a delegation field which is identical to the target name of that join type, the whole object(s) will be captured.
user_collection.join_to(:site, Site, :relation => {:site_id => :id}, :delegation => {:fields => [:site]})
user_collection.source_objects.first.site # get the site the user belongs to
user_collection.join_one(:profile, Profile, :relation => {:user_id => :id}, :delegation => {:fields => [:profile]})
user_collection.source_objects.first.profile # get the profile the user has
user_collection.join_many(:contacts, Contact, :relation => {:user_id => :id}, :delegation => {:fields => [:contacts]})
user_collection.source_objects.first.contacts # get all contacts the user has
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request