-
-
Save jsmestad/993978 to your computer and use it in GitHub Desktop.
@snapshot = Snapshot.first | |
----- | |
{ | |
:stats => { | |
'accounts' => { 'count' => 8 }, | |
'subscriptions' => { 'count' => 16 } | |
}, | |
: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 | |
---- | |
@snapshot.select('stats.*', :count => 16) # would search all sub-hashes that match the query, returning the hash containing the value | |
@snapshot.select('activity.*', :ns => /^accounts\.$/) # would return the sub-hash that matches the query in the array | |
----- | |
@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 } |
class Snapshot | |
include Mongomatic # this will replace Mongomatic::Base, its like saying 'normal defaults' | |
include Mongomatic::Sanitize | |
attribute :database_id, :typed => Integer, :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 | |
indexes do |collection| | |
collection.ensure_index([['database_id', Mongo::ASCENDING], ['created_at', Mongo::DESCENDING]], :unique => true) | |
end | |
end |
I think object serialization and handling of DateTime/etc objects are something we should address for sure (actually there was a lot of discussing on how to do the latter at the Ruby talk at MongoSF). However, I do think I was addressing a third use case with this: handling data from forms. The mongo driver casts to the correct mongo type but it doesn't cast "1.23" to its float equivalent, etc. If you have a lot of things like checkboxes or textfields to take numbers having some "type casting" like that can reduce/simplify code. IMO, useful when writing something like an admin tool and I think making writing admin screens for Shadelight easier was one of the reasons Ben built typed fields. Also, its not hard to build your own Mongomatic::TypeConverters and have custom "casters", which could lead to some cool stuff. But like I said before, I'm not dead set on implementing it this way, it just happens to be how I was first inclined to build and use it. We can always rip it out and rewrite it with a focus solely on serialization.
For example something like:
# some rails action
def my_action
item_instance = Item.new # some Mongomatic model instance
item_instance['avail_for_purchase'] = params[:item][:avail_for_purchase] == "1" ? 1 : 0
item_instance['price'] = params[:item][:price].to_f # lets just hope in this example we get a proper dollar value
# lots more control statements & setting of values
#...
end
just becomes:
def my_action
item_instance.new(params[:item])
end
Two use-cases we could address with this:
1.) Object Serialization -- So I think if you want casting, it should be done bi-directionally. This way you can have something that is an object (think YAML serialization) and then cast it back as an object of specified Class when its pulled out.
2.) DateTime/Time/Date objects -- Again bi-directional is useful if you have something where you save a Date.today, and when you pull it back out, it should still be only a Date object and not the MongoDB Time object (and not UTC for example).
The rest of it is just verbose crap since the mongodb ruby driver handles converting of standard Ruby formats. Maybe we should change the syntax to something like...
This way you can do
@record.snapshots.class # => [<#Snapshot>,<#Snapshot>,....]