Skip to content

Instantly share code, notes, and snippets.

@jrwest
Forked from jsmestad/accessing_snapshot.rb
Created May 26, 2011 22:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrwest/994253 to your computer and use it in GitHub Desktop.
Save jrwest/994253 to your computer and use it in GitHub Desktop.
Proposed changes for Mongomatic 0.9.0 (Jordan's Edits)
@snapshot = Snapshot.first
-----
{
:stats => {
'accounts' => { 'count' => 8, 'a' => 1 },
'subscriptions' => { 'count' => 16, 'b' => 1 }
},
:activity => [ {'ns' => 'accounts.users', ...}, {'ns' => 'subscriptions.users' =>, ...} ]
}
-----
# Attribute definitions would be defined as instance method accessors
#
# For example:
# def database_id; self.doc[:database_id]; end
@snapshot.database_id
@snapshot.created_at
@snapshot.stats
----
# select should always return an array even if it matches a single hash
@snapshot.select('stats.*', :count => 16) # => [{'count' => 16, 'b' => 1}]
# not sure which of the next two I prefer
@snapshot.select('stats.*') do |sub_hash|
sub_hash['count'].to_i >= 8
end # => [{'count' => 8, 'a' => 1}, {'count' => 16, 'b' => 1}]
@snapshot.select('stats.*', count: ->(c) { c >= 8 }) # i think when you want to test more than one key, the first one will be cleaner
@snapshot.select('activity.*', :ns => /^accounts\.$/) # would return an array of sub-hashes that matches the query in the array
# if select always returns an array its a nice extension to allow you it iterate with each
@snapshot.each('activity.*', :ns => /^accounts\.$/) do |hash|
# ...
end
-----
@snapshot['stats.accounts.count'] # => 8
@snapshot['stats.posts.count'] # => nil
@snapshot.doc(['stats.posts.count'], true|false) # => KeyDoesNotExist, 'stats.posts does not exist in the document hash, true is the default here as your assuming the hash exists at the doc level
# Assignment -- not sure about this one.
@snapshot['stats.posts.count'] = 8 # => {:stats => { 'posts' => { 'count' => 8 } } } but raise error if the type is an Array.
@snapshot['stats.*.count'] = 8 # => mass assignment to doc[:stats].each {|x| x[:count] = 8 }
# Example of Modifier Chaining: Use multiple modifier methods (fastmods) in one update query
# Some things to address:
# * do we raise errors or let mongo do it if you try to fastmod the same key twice in a chain
# * are all the different interfaces needed (explicit, block, chain)? (see three examples)
# * my first implementation of this made the update safe if a single mod! method was called in the chain
# mongoo does this instead by having #start_modifier_chain and #start_modifier_chain! (its called something
# different in mongoo).
class GameObject
include Mongomatic
include Montomatic::ModifierChain # not sure if we want this in a sep. module or not
attribute :silver_amt, typed: Fixnum
attribute :gold_amt, typed: Fixnum
attribute :facebook_friends, typed: Array
attribute :friends_total_animal_count, typed: Integer
def inc_gold_and_silver(gold, silver)
self.start_modifier_chain
self.inc('gold', gold)
self.inc('silver', silver)
self.flush_modifier_chain
end
def add_friend(id, animal_count)
self.start_modifier_chain do |game_obj| # this is more useful when working outside of instance methods and not using self
game_obj.push('facebook_friends', id)
game_obj.inc('friends_total_animal_count', animal_count)
end
end
def buy_friends_animal(gold_cost)
start_modifier_chain.inc('gold', 0 - gold_cost).inc('friends_total_animal_count', -1).flush_modifier_chain
end
end
class Snapshot
include Mongomatic # this will replace Mongomatic::Base, its like saying 'normal defaults'
include Mongomatic::Sanitize
attribute :database_id, :typed => Fixnum, :required => true
attribute :created_at, :typed => Time, :required => true
attribute :stats, :typed => Hash, :required => true
sanitize_keys # will do the entire document
sanitize_keys :stats, :replace_with => '#', :depth => 2 # various options we could support
# class method to define indexes, it does not create the index on load, but says, if you call
# Snapshot.create_indexes I will create this index for you
# same as:
# def create_indexes
# collection.ensure_index([['database_id', Mongo::ASCENDING], ['created_at', Mongo::DESCENDING]], :unique => true)
# end
#
# still must pass array of arrays to "on" because no order preservation in 1.8 hashes
# this does not create the index, it just says, if you call Snapshot.create_indexes
# then it will be called
index on: [['database_id', Mongo::Ascending], ['created_at', Mongo::DESCENDING]], opts: {unique: true}
end
@jsmestad
Copy link

I like the class level DSL, or a class method. This would not be evaluated on load of the class. Its more so we can do...

Note: @loaded_classes is a list of all the loaded classes defined in lets say Rails.root/app/models/*/

@loaded_classes.each { |class| class.ensure_indexes if class.respond_to?(:ensure_indexes) }

Which would make having a rake task & cap task easy for ensuring indexes. Also it also has a standard location for viewing indexes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment