ActiveMongoid facilitates usage of both ActiveRecord and Mongoid in a single rails application by providing an ActiveRecord-like interface for inter-ORM relations. It was written to replace select Mongoid models with ActiveRecord versions so it tries to adhere to the Mongoid API as closely as possible. To accomplish this compatibility, much of the logic and structure of this lib are either directly inspired by or straight up ripped off the Mongoid source.
Add this line to your application's Gemfile:
gem 'active_mongoid'
And then execute:
$ bundle
Or install it yourself as:
$ gem install active_mongoid
To add ActiveMongoid associations, simply add the ActiveMongoid::Associations
module in both models and define the relations using the provided macros as you would with either ActiveRecord or Mongoid.
class Player < ActiveRecord::Base
include ActiveMongoid::Associations
belongs_to_document :team
has_one_document :stat, as: :target, autosave: true, dependent: :destroy
end
class Team
include Mongoid::Document
include ActiveMongoid::Associations
has_many_records :players, autosave: true, order: "name asc"
belongs_to_record :division
end
Then you can interact with the models and relations just as you would with either ActiveRecord or Mongoid.
> team = Team.create
=> #<Team _id: 5453d55cb736b692ab000001, name: nil>
> player = team.players.build(name: "foo") # create will call save
=> #<Player id: nil, name: "foo", team_id: "5453d55cb736b692ab000001">
> team.player << Player.new(name: "foo1")
=> #<Player id: nil, name: "foo1", team_id: "5453d55cb736b692ab000001">
> team.players
=> [#<Player id: nil, name: "foo", team_id: "5453d55cb736b692ab000001">, #<Player id: nil, name: "foo1", team_id: "5453d55cb736b692ab000001">]
> player.team # binds the inverse
=> #<Team _id: 5453d55cb736b692ab000001, name: nil>
> team.save
=> true
> team.players
=> [#<Player id: 1, name: "foo", team_id: "5453d55cb736b692ab000001">, #<Player id: 2, name: "foo1", team_id: "5453d55cb736b692ab000001">]
> team.players.where(name: "foo") # returns relation so chaining is possible
=> [#<Player id: 1, name: "foo", team_id: "5453d55cb736b692ab000001">]
> team.players.where(name: "foo").where(id: 1)
=> [#<Player id: 1, name: "foo", team_id: "5453d55cb736b692ab000001">]
> player = Player.create(name: "baz")
=> #<Player id: 3, name: "baz", team_id: nil>
> team = player.build_team(name: "bar") # create_ will call save
=> #<Team _id: 5453d55cb736b692ab000002, name: "bar">
> team.players
=> [#<Player id: 3, name: "foo", team_id: "5453d55cb736b692ab000002">]
> player.team(true) # forces reload from database
=> nil
has_many_records :players
has_many_documents :stats
Options:
order
Needs to be formated according to ActiveRecord/Mongoid spec respectivelydependent
Accepts::destroy, :delete
as
Polymorphic relationforeign_key
Foreign key for relationprimary_key
Primary key for relationclass_name
Association class nameautosave
Accepts:true
has_one_record :player
belongs_to_record :player
has_one_record :stat
belongs_to_record :stat
Options:
dependent
Accepts::destroy, :delete
as
Polymorphic relationforeign_key
Foreign key for relationprimary_key
Primary key for relationclass_name
Association class nameautosave
Accepts:true
team.players
Returns the relationteam.players(true)
Forces reload from database and returns relationteam.players = [player]
Assigns objects and calls dependent method on old valuesteam.players << player
Appends object and will save if base is persistedteam.players.build({player.attributes})
Builds and binds object from attributes and binds relationteam.players.concat([player_1, player_2]
Appends and binds array of objects. Will save if base is persistedteam.players.purge
Removes all objects from relation and calls dependent method on objectsteam.players.delete(player)
Removes object and calls dependent method on objectteam.players.delete_all(optional_criteria)
Calls delete on all objectsteam.players.destroy_all(optional_criteria)
Calls destroy on all objectsteam.players.each
Iterates on on objectsteam.players.exists?
Calls exists? on relationteam.players.find(params)
Returns relation with criteria addedteam.players.nullify
Clears loaded relationteam.players.blank?
Returnstrue
if emptyteam.players.create({player.attributes})
Creates and binds from attributesteam.players.create!({player.attributes})
Creates and binds form attributes and raises an exception if failsteam.players.find_or_create_by({player.attributes})
Finds or creates a record from attributesteam.players.find_or_initialize_by({player.attributes})
Finds or initializes a record from attributesteam.players.nil?
returnsfalse
All other methods will defer to the ActiveRecord/Mongoid relation respectively.
player.stat
Returns the relationplayer.stat(true)
Forces reload from database and returns relationplayer.stat = stat
Assigns object as relation. Will substitute old value and call dependent methodplayer.build_stat({})
Builds and binds new object from attributesplayer.create_stat({})
Creates and binds new object from attributes
All other methods called on relation will defer to the object.
The BsonId module faciliates the useage of BSON::ObjectId
's on ActiveRecord objects. This module is especially helpful if you are migrating a model from a Mongoid object to an ActiveRecord object and want to carry over the old id.
class Division < ActiveRecord::Base
include ActiveMongoid::BsonId
bsonify_attr :_id, initialize: true
end
> division._id
=> BSON::ObjectId('545289a7b736b6586a000001')
> division._id = BSON::ObjectId('545289a7b736b6586a000002')
=> BSON::ObjectId('545289a7b736b6586a000002')
> division._id = '545289a7b736b6586a000002'
=> BSON::ObjectId('545289a7b736b6586a000002')
class Play < ActiveRecord::Base
include ActiveMongoid::Associations
include ActiveMongoid::Finders
include ActiveMongoid::BsonId
bsonify_attr :id, initialize: true, primary: true
end
> play.id
=> '545289a7b736b6586a000001' # An issue with ActiveRecord does not allow casting this particular accessor
> play.id = BSON::ObjectId('545289a7b736b6586a000002')
=> BSON::ObjectId('545289a7b736b6586a000002')
> play._id = '545289a7b736b6586a000002'
=> BSON::ObjectId('545289a7b736b6586a000002')
This module proxies the existing ActiveRecord find
and where
to perform casting of BSON::ObjectId
's to string for queries. Additionally it'll default to the _id
field if the object is a valid BSON::ObjectId
and the _id
field is present on the model.
class Division < ActiveRecord::Base
include ActiveMongoid::BsonId
include ActiveMongoid::Finders
bsonify_attr :_id, initialize: true
end
> Division.find(1)
=> #<Division id: 1, _id: "545289a7b736b6586a000001", name: "new">
> Division.find(BSON::ObjectId('545289a7b736b6586a000001')
=> #<Division id: 1, _id: "545289a7b736b6586a000001", name: "new">
> Division.where(_id: BSON::ObjectId('545289a7b736b6586a000001')
=> [#<Division id: 1, _id: "545289a7b736b6586a000001", name: "new">]
> Division.where(id: BSON::ObjectId('545289a7b736b6586a000001')
=> [#<Division id: 1, _id: "545289a7b736b6586a000001", name: "new">]
- Fork it ( https://github.com/[my-github-username]/active_mongoid/fork )
- 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 a new Pull Request