README.rdoc in doeskeyvalue-0.2.2 vs README.rdoc in doeskeyvalue-0.9.0

- old
+ new

@@ -1,104 +1,139 @@ = DoesKeyValue -Bring the fun of NoSQL into your SQL-backed Active Record objects in a compartmentalized way. Turns -any text field on your objects into a schema-less key value store. +NoSQL-like key value stores in SQL-backed ActiveRecord objects. Arbitrary keys behave +like dynamic, indexable, searchable first-order attributes. +== Deprecation Notice +DoesKeyValue is undergoing a substantial API change in order to better support new features +and alter the approach to previously-included features. The "old" gem versions will have +number in the v0.2.* series and are maintained (though only for major bugfixes) on the +{"albus" branch}[https://github.com/awexome/doeskeyvalue/tree/albus] in the repository. +Going forward, new work on the gem will be of the v0.9.* version series and will be +completed in {"bellatrix" branch}[https://github.com/awexome/doeskeyvalue/tree/bellatrix] +and made available in master. + +When ready, the new "bellatrix" API will be released as a public gem with v0.9.0, but until +then, users can live on the edge by referencing this repository (master or bellatrix branches) +in their Gemfiles. + +This documentation refers to only the new/v0.9+ branch and its corresponding API. + + == Installation -Do the usual, of course: +Tried and true: gem install doeskeyvalue And add a gem dependency to your Gemfile: - gem "doeskeyvalue", ">=0.1.0" + gem "doeskeyvalue" -== Example +== Column-Based Storage Example -Quick and simple. First, add the declaration to your ActiveRecord model: +In any ActiveRecord model in which you'd like to have key-value support, you simply +declare your intention to declare keys: - doeskeyvalue :settings + does_keys :column=>"settings" -In this invocation, "settings" is the name of TEXT or BLOB field on your model's database table. Think -of it as something you'd typically serialize, but would prefer solid accessor and finding behavior on. +In this invocation, "settings" is the name of TEXT or BLOB field on your model's database +table. Think of it as something you'd typically serialize, but would prefer solid accessor +and finding behavior on. -To add keys to your document, using the name of the field you provided, before (in this case -"settings"), add keys individually like so: +Add keys to your document field individually like so: - settings_key :uid - settings_key :email - settings_key :name - -This adds a uid, email, and name field to your record. You can use these fields just like regular -columns on your ActiveRecord object, but they're happily stored within your TEXT/BLOB column at the -database level. Check it out: + has_key :email # Default type is string + has_key :uid, :type=>:integer # But type can be overidden easily + has_key :city, :default=>"Awesomeville" # You can also declare default values +This adds email, uid, and city fields to your record. You can use these fields just like regular +columns on your ActiveRecord object, but they're happily stored within your TEXT/BLOB column at +the database level. Check it out: + mod = Model.new + mod.email = "me@awexo.me" + => "me@awexo.me" + mod.email + => "me@awexo.me" - mod.uid = "mccolin" - => "mccolin" - - mod.uid - => "mccolin" - -You can see the serialized key-value structure at any time, as well. Just access your old filed: +You can see the serialized key-value structure at any time, as well. Just access your old field: mod.settings - => {:uid=>"mccolin"} - -At this point, we have a fancy serialized Hash on our hands. What we really want to be able to do is -search for objects of type Model that have certain values. That's possible, too. First, generate the -necessary migration: + => {:email=>"me@awexo.me"} - rails g doeskeyvalue - -This creates db/migrate/XXX_create_key_value_index.rb for you. Migrate your database: - rake db:migrate - -Now, you can declare keys that you'd like to be searchable within Model like so: +=== Indexes and Searchability - settings_index :uid - settings_index :email - -Now, you've added powerful finders to your objects. As your objects are created, accessed, and updated, -metadata in your index table will be updated that allows you to search against those objects similarly -to how you'd perform lookups with a regular finder. Like so: +By default, all keys specified in column-based storage also have indexes which provide scopes +and searchability. This behavior, however, requires the addition of an key index database table, +which you can generate on the command line: - Model.find_all_by_uid(123) - => [#<Model:0x000001016b51a0 @settings=>{:uid=>123}>, #<Model:0x000001016b51a0 @settings=>{:uid=>123}>, ...] - - Model.find_all_with_settings(:email=>"foo@bar.com") - => [#<Model:0x000001016b51a0 @settings=>{:email=>"foo@bar"}>, ...] + > rails generate doeskeyvalue + > rake db:migrate -You can only run finds on keys for which you've added an index, but you can add and remove indexes as -necessary simply by removing the index declaration from your model. +This will add a +key_value_index+ table to your database, which will serve as an application-wide +index and cache of your declared keys. Key values you modify on your objects are stored/cached +within the +key_value_index+ table, which is used in lookups. -Likewise, you can remove keys from any model by removing the key declaration. This allows you to add -and remove keys from every ActiveRecord object at will, without having to build any migrations, but you -can still reap the benefits of whatever SQL-backed relational database you've chosen for the bulk of -your application's heavy lifting. +For each key, a default scope of the form "with_KEYNAME" is provided for your use: + Model.with_email("foo@bar.com") + => [] + Model.with_email("me@awexo.me") + => [#<User id: 1, ..., settings: {"email"=>"me@awexo.me"}, ...>] -== Prior Versions +If you'd prefer to not have this searchability, you can forgo the creation of an index and related +scope for any of your keys, like so: -DoesKeyValue is a much newer and cleaner version of the old "do_document_fields" plugin for prior versions -of Rails. Check that out at http://github.com/mccolin/do_document_fields + has_key :email, :index=>false # Deny index creation (default setting for index is true) +Naturally, if all of your keys omit an index, you will not require the +key_value_index+ table in +your project. -== Contributions - -* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet -* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it -* Fork the project -* Start a feature/bugfix branch -* Commit and push until you are happy with your contribution -* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally. -* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it. -== Copyright +== Table-Based Storage Example -Copyright (c) 2011 Awexome Labs, LLC. http://awexomelabs.com/ +For larger key sets, you may find it advantageous to move your key-value storage into a separate +database table altogether, instead of the baked-in serialized TEXT/BLOB column. You can do this +quite easily by using a different flag in your initialization call: + does_keys :table=>"user_preferences" + +In this example, we're storing our key-value pairs as their own independent rows within the +user_preferences database table. You declare keys and manipulate values in exactly the same way +as before: + + has_key :bgcolor, :default=>"blue" + has_key :birthday, :type=>:datetime + has_key :likes_ice_cream, :type=>:boolean, :default=>true + + mod.likes_ice_cream + => true + mod.likes_ice_cream = false + => false + mod.bgcolor + => "blue" + +However, unlike with column-based storage, these values are immediately written to the table +specified in the invocation (in this case, +user_preferences+). + +You will need to generate your separate key value indexes using the generator, while providing +a table name: + + > rails generate doeskeyvalue user_preferences + > rake db:migrate + +All keys using the separate table-based storage approach are automatically indexed. Values are +read directly from the supporting index table. + +If desired, multiple models can freely store their values in a single table. This may be desired +for locality of all settings across a varieties of classes. You could, for instance, create one ++preferences+ table, which collects key values from User, Account, and Post models. For each class, +the invocation to +does_keys+ is the same. Simple! + + +== Copyright + +Copyright (c) 2012 Awexome Labs, LLC. http://awexomelabs.com/