Skip to content

Facilitates performing queries on collections in embedded Mongoid documents

Notifications You must be signed in to change notification settings

kristianmandrup/mongoid_embedded_helper

Repository files navigation

Mongoid embedded helper

The Mongoid EmbeddedHelper helps overcome the limitation that you can’t perform direct queries on an embedded collection without accessing it from the root.
It simply introduces a generic function that performs the “local” query by accessing it from the nearest root ;)

Update June 24, 2011

In the latest release (0.3.1) the gem has been tested to work with Mongoid 2.0.2 (run the specs!)

Install

In Gemfile:

gem 'mongoid_embedded_helper'

Run bundler

$ bundle

Usage

Mongoid doesn’t allow you to perform direct queries on an embedded collection. You have to access the embedded collection from the root in order to do this.
To overcome this limitation, use the EmbeddedHelper module to add a method query_class which will find the closest non-embedded node in the hierarchy and
then traverse down the path back to the object, so that you can perform the query on the embedded collection.

require 'mongoid_embedded_helper'

class Item
  include Mongoid::Document
  include Mongoid::EmbeddedHelper
  field :pos, :type => Integer
  field :number, :type => Integer

  field :assoc, :type => Symbol
  embedded_in :list, :inverse_of => :items
end

item = @person.lists[0].items[0]
item.query_class.where(:number.gt => 1).to_a

Adjust!

An as added bonus, an extra adjust! method has been added to Document, Criteria and Array. This enables multi-mutation of attributes!
This functionality comes along from the mongoid_adjust gem.

Here an example using a number

it "should times all positions (greater than 1) by 2" do
  result = @person.lists[0].items.where(:pos.gt => 1).adjust!(:pos => lambda {|e| e * 2})
  result.map(&:pos).should == [4, 6]
end

Passing a number is a convenience shortcut for adding a number instead of having to use the Proc approach as shown below.

Here an example using a lambda (or Proc):

it "should times all positions (greater than 1) by 2" do
  result = @person.lists[0].items.where(:pos.gt => 1).adjust!(:pos => lambda {|e| e * 2})
  result.map(&:pos).should == [4, 6]
end

The Proc approach can in simple cases be declared using a shortcut Symbol/String approach

Here an example using a symbol :upcase to declare that the method #upcase should be used as the mutator:

  it "should upcase the name - using symbol arg" do
    result = @person.adjust!(:name => :upcase)
    result.name.should == 'Kristian'.upcase
  end

And using a String ‘upcase’ instead of a symbol:

  it "should upcase the name - using symbol arg" do
    result = @person.adjust!(:name => 'upcase')
    result.name.should == 'Kristian'.upcase
  end

Copyright

Copyright © 2010 Kristian Mandrup

About

Facilitates performing queries on collections in embedded Mongoid documents

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages