MarkMapper provides support for Dynamic Querying in its finders, familiar to many Rails developers. Similar to dynamic finders in ActiveRecord , MarkMapper provides a finder for every key defined in your document.
Let’s start with a simple User model:
class User
include MarkMapper::Document
key :first_name, String
key :last_name, String
key :age, Integer
scope :smiths, where(:last_name => "Smith")
scope :johns, where(:first_name => "John")
end
Let’s create some users that we can query dynamically later:
User.create(:first_name => "Ann", :last_name => "Smith", :age => 24)
User.create(:first_name => "John", :last_name => "Smith", :age => 42)
User.create(:first_name => "John", :last_name => "Zoidberg", :age => 46)
We can now dynamically query for a user by one or multiple keys like so:
User.find_by_first_name("Ann")
User.find_by_first_name_and_last_name_and_age("John","Zoidberg",46)
In order to query for all possible users simply add the all keyword to the query which will return an array of results
User.find_all_by_last_name("Smith").length # => 2
Remember the scopes that we defined in our User class earlier? Well MarkMapper allows you to dynamically query those scopes too:
User.johns.find_by_last_name("Zoidberg")
User.smiths.find_all_by_age(24)
Another convenient feature that MarkMapper provides (similar to ActiveRecord) is the ability to find or initialize a record by one or more keys:
User.find_or_initialize_by_last_name("Nunemaker")
User.find_or_initialize_by_first_name_and_last_name("Haris","Amin")
In the above queries, if a user is not found, the user is then initialized with the attributes given to the dynamic query. If you want to save and actually create those records using dynamic finders, you can write the above queries like so:
User.find_or_create_by_last_name("Nunemaker")
User.find_or_create_by_first_name_and_last_name("Haris","Amin")
Dynamic Querying also has support for the ! operator. So if a document is not found in a dynamic query using the ! operator, an exception will be raised likewise:
User.find_by_first_name_and_last_name!("Why", "The Lucky Stiff") # => MarkMapper::DocumentNotFound: Couldn't find Document with {"first_name"=>"Why", "last_name"=>"The Lucky Stiff"} in collection named users