doeskeyvalue 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # AWEXOME LABS
2
+ # Gemfile
3
+
4
+ source "http://rubygems.org"
5
+
6
+ # Runtime dependencies:
7
+
8
+
9
+ # Development dependencies:
10
+ group :development do
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.5.2"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.2)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 1.0.0)
16
+ jeweler (~> 1.5.2)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Awexome Labs, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,98 @@
1
+ = DoesKeyValue
2
+
3
+ Bring the fun of NoSQL into your SQL-backed Active Record objects in a compartmentalized way. Turns
4
+ any text field on your objects into a schema-less key value store.
5
+
6
+
7
+ == Installation
8
+
9
+ Do the usual, of course:
10
+
11
+ gem install doeskeyvalue
12
+
13
+ And add a gem dependency to your Gemfile:
14
+
15
+ gem "doeskeyvalue", ">=0.0.1"
16
+
17
+
18
+ == Example (TODO: Update this with new API)
19
+
20
+ To add document_fields to your ActiveRecord object, first add a text column to your class' backing table that will hold your document content. By default, do_document_fields will expect this column to be named "document", but you can override that easily.
21
+
22
+ Once you've migrated that change into your model, here's a sample of hold to add document-style blob fields to your object:
23
+
24
+ class ObjectWithBlob < ActiveRecord::Base
25
+
26
+ # Declare that we are using document blobs in a particular column of this object:
27
+ do_document_fields
28
+
29
+ # Declare the columns we are adding to our document:
30
+ document_field :name, String
31
+ document_field :phone, String
32
+ document_field :age, Integer
33
+
34
+ # Declare the document fields you'd like to track with indexes:
35
+ document_index :name
36
+
37
+
38
+ # If we wanted to change the name of the column in which we store the document, we'd do this:
39
+ # do_document_fields :something_other_than_document. Like so:
40
+
41
+ do_document_fields :settings
42
+
43
+ # Changing the name of the column gives you a specifically-formatted field-definition method:
44
+
45
+ settings_field :age
46
+ settings_field :sex
47
+ settings_field :location
48
+
49
+ # This also provides a customized way to index:
50
+
51
+ settings_index :location
52
+
53
+ end
54
+
55
+
56
+ Now, you can add and remove new fields to this object within the document as simply as adding or removing declarations of "document_field".
57
+
58
+
59
+ Once you've added any indices to your model's fields, you'll want to be sure to build your supporting index tables. We use separate tables with database-level indexing to support indexed lookups of data in your document_field attributes. Build these tables by running this rake task:
60
+
61
+ rake db:migrate:document_indexes
62
+
63
+
64
+ Now, you can use strictly-provided finders to find your objects by their document field attributes. Considering the model we described above, you can lookup by any *indexed* field like so:
65
+
66
+ obj = ObjectWithBlob.find_by_name("Charlie")
67
+ => [#<ObjectWithBlob id: 412, document: {:name=>"Charlie", :phone=>"212-555-1234", :age=>34}, created_at: "2010-03-22 20:49:03", updated_at: "2010-03-22 20:49:03">]
68
+
69
+ Finders are only added to document fields that are indexed. Finders also are all "find_all" lookups on equality.
70
+
71
+ If you'd like to use special sub-searching within any of your document-formatted fields, you can use the hash-based search conditions. Given the "settings" document declared in the example above, we can now also do this:
72
+
73
+ obj = ObjectWithBlob.find_with_settings(:location=>"San Francisco, CA")
74
+ => [#<ObjectWithBlob id: 412, settings: {:age=>32, :sex=>"Female", :location=>"San Francisco, CA"}, created_at: "2010-03-22 20:49:03", updated_at: "2010-03-22 20:49:03">]
75
+
76
+ It's simple.
77
+
78
+
79
+ == Prior Versions
80
+
81
+ DoesKeyValue is a much newer and cleaner version of the old "do_document_fields" plugin for prior versions
82
+ of Rails. Check that out at http://github.com/mccolin/do_document_fields
83
+
84
+
85
+ == Contributions
86
+
87
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
88
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
89
+ * Fork the project
90
+ * Start a feature/bugfix branch
91
+ * Commit and push until you are happy with your contribution
92
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
93
+ * 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.
94
+
95
+ == Copyright
96
+
97
+ Copyright (c) 2011 Awexome Labs, LLC. http://awexomelabs.com/
98
+
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # AWEXOME LABS
2
+ # Rakefile
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+ require 'rake'
14
+
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "doeskeyvalue"
19
+ gem.homepage = "http://github.com/awexome/doeskeyvalue"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Add schema-less NoSQL-like key values to any ActiveRecord class}
22
+ gem.description = %Q{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.}
23
+ gem.email = "gems@awexomelabs.com"
24
+ gem.authors = ["Awexome Labs"]
25
+
26
+ # Internal Gem Dependencies:
27
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rake/rdoctask'
33
+ Rake::RDocTask.new do |rdoc|
34
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
35
+
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = "doeskeyvalue #{version}"
38
+ rdoc.rdoc_files.include('README*')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{doeskeyvalue}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Awexome Labs"]
12
+ s.date = %q{2011-02-15}
13
+ s.description = %q{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.}
14
+ s.email = %q{gems@awexomelabs.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "doeskeyvalue.gemspec",
28
+ "lib/doeskeyvalue.rb",
29
+ "lib/doeskeyvalue/indexes.rb",
30
+ "lib/doeskeyvalue/keys.rb",
31
+ "lib/doeskeyvalue/util.rb",
32
+ "lib/generators/doeskeyvalue/doeskeyvalue_generator.rb",
33
+ "lib/generators/doeskeyvalue/templates/create_key_value_index.rb"
34
+ ]
35
+ s.homepage = %q{http://github.com/awexome/doeskeyvalue}
36
+ s.licenses = ["MIT"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.5.2}
39
+ s.summary = %q{Add schema-less NoSQL-like key values to any ActiveRecord class}
40
+
41
+ if s.respond_to? :specification_version then
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
46
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
47
+ else
48
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
54
+ end
55
+ end
56
+
@@ -0,0 +1,84 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+ #
4
+ # Indexes -- ActiveRecord::Base methods for settings and retrieval of values based
5
+ # on key indexes
6
+
7
+ module DoesKeyValue
8
+ module Indexes
9
+
10
+ def declare_index(key_value_column, key_name, opts={})
11
+ puts "DOES_KEY_VALUE: Index declared: #{key_value_column}, #{key_name}, #{opts.inspect}"
12
+ raise DoesKeyValue::NoColumnNameSpecified unless key_value_column
13
+ raise DoesKeyValue::NoKeyNameSpecified unless key_name
14
+ raise DoesKeyValue::KeyAndIndexOptionsMustBeHash unless opts.is_a?(Hash)
15
+
16
+ search_key = "#{key_value_column}.#{key_name}"
17
+ raise DoesKeyValue::NoKeyForThatIndex if !self.respond_to?(key_name) || !self.respond_to?("#{key_name}=")
18
+
19
+ class_name = self.name.underscore
20
+ class_table_name = self.table_name
21
+ index_table_name = "key_value_index"
22
+
23
+ # INDEX TABLE: key_value_index
24
+ # id:int
25
+ # key_name:string
26
+ # value:string
27
+ # obj_type:string
28
+ # obj_id:int
29
+
30
+ # Define finders that leverage the custom index table:
31
+ instance_eval <<-EOS
32
+ def find_all_by_#{key_value_column}_#{key_name}(value)
33
+ find(
34
+ :all,
35
+ :select=>"*",
36
+ :from=>"#{index_table_name}",
37
+ :conditions=>["`#{index_table_name}`.obj_type = ? AND `#{index_table_name}`.key_name = ? AND `#{index_table_name}`.value = ?", self.to_s, "#{search_key}", value],
38
+ :joins => "LEFT JOIN `#{class_table_name}` ON `#{class_table_name}`.id = `#{index_table_name}`.obj_id"
39
+ )
40
+ end
41
+
42
+ def find_all_by_#{key_name}(value)
43
+ find_all_by_#{key_value_column}_#{key_name}(value)
44
+ end
45
+
46
+ def find_all_with_#{key_value_column}(opts={})
47
+ conds = Array.new
48
+ opts.each do |k, v|
49
+ conds.add_condition(["`#{index_table_name}`.obj_type = ? AND `#{index_table_name}`.key_name = ? AND `#{index_table_name}`.value = ?", self.to_s, "#{search_key}", v])
50
+ end
51
+ find(
52
+ :all,
53
+ :select=>"*",
54
+ :from=>"#{index_table_name}",
55
+ :conditions=>conds,
56
+ :joins=>"LEFT JOIN `#{class_table_name}` ON `#{class_table_name}`.id = `#{index_table_name}`.obj_id"
57
+ )
58
+ end
59
+ EOS
60
+
61
+ # Provide a callback after save which updates the index
62
+ define_method("update_index_#{key_value_column}_#{key_name}_after_save") do
63
+ class_name = self.class.name.underscore
64
+ class_table_name = self.class.table_name
65
+ index_table_name = "key_value_indexes"
66
+ # TODO: Restrict value to 255 characters, the table-enforced limit
67
+ idx_id = ActiveRecord::Base.connection.insert("INSERT INTO `#{index_table_name}` (`obj_type`,`obj_id`,`key_name`,`value`) VALUES (\""+self.class.to_s+"\","+self.id.to_s+", \""+search_key.to_s+"\", \"#{self.send(key_name).to_s}\")")
68
+ end
69
+ after_save "update_index_#{key_value_column}_#{key_name}_after_save"
70
+
71
+ # Provide a callback after destroy to likewise update the index
72
+ define_method("update_index_#{key_value_column}_#{key_name}_after_destroy") do
73
+ class_name = self.class.name.underscore
74
+ class_table_name = self.class.table_name
75
+ index_table_name = "key_value_indexes"
76
+ num_del = ActiveRecord::Base.connection.delete("DELETE FROM `#{index_table_name}` WHERE `obj_type` = \"#{self.class}\" AND `obj_id` = #{self.id}")
77
+ end
78
+ after_destroy "update_index_#{key_value_column}_#{key_name}_after_destroy"
79
+
80
+ end
81
+
82
+
83
+ end # Index
84
+ end # DoesKeyValue
@@ -0,0 +1,40 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+ #
4
+ # Keys -- ActiveRecord::Base methods for setting schemaless keys
5
+
6
+ module DoesKeyValue
7
+ module Keys
8
+
9
+ def declare_key(key_value_column, key_name, opts={})
10
+ puts "DOES_KEY_VALUE: Key declared: #{key_value_column}, #{key_name}, #{opts.inspect}"
11
+ raise DoesKeyValue::NoColumnNameSpecified unless key_value_column
12
+ raise DoesKeyValue::NoKeyNameSpecified unless key_name
13
+ raise DoesKeyValue::KeyAndIndexOptionsMustBeHash unless opts.is_a?(Hash)
14
+
15
+ # Define accessors for the key column in the AR class:
16
+ class_eval <<-EOS
17
+ def #{key_name}
18
+ puts "DOES_KEY_VALUE: Accessor for `#{key_name}` invoked"
19
+ return (self.send(:#{key_value_column}) || Hash.new)[:#{key_name}]
20
+ end
21
+ puts "DOES_KEY_VALUE: Key accessor `#{key_name}` declared"
22
+
23
+ def #{key_name}=(value)
24
+ puts "DOES_KEY_VALUE: Setter for `#{key_name}` invoked"
25
+ key_set = self.send(:#{key_value_column}) || Hash.new
26
+ key_set[:#{key_name}] = value
27
+ self.send("#{key_value_column}=", key_set)
28
+ end
29
+ puts "DOES_KEY_VALUE: Key manipulator `#{key_name}=` declared"
30
+ EOS
31
+
32
+ # Check for opts[:index=>true] and if present, call declare_index
33
+ if opts[:index] == true
34
+ declare_index(key_value_column, key_name) # TODO: Provide mechanism for passing index options
35
+ end
36
+
37
+ end
38
+
39
+ end # Keys
40
+ end # DoesKeyValue
@@ -0,0 +1,27 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+
4
+
5
+ module DoesKeyValue
6
+ module Util
7
+
8
+ module CondArray
9
+ def add_condition(cond, conj="AND")
10
+ if cond.is_a?(Array)
11
+ if self.empty?
12
+ (self << cond).flatten!
13
+ else
14
+ self[0] += " #{conj} #{cond.shift}"
15
+ (self << cond).flatten!
16
+ end
17
+ elsif cond.is_a?(String)
18
+ self[0] += " #{conj} #{cond}"
19
+ else
20
+ raise "Condition must be an Array or String"
21
+ end
22
+ self
23
+ end
24
+ end
25
+
26
+ end
27
+ end # DoesKeyValue
@@ -0,0 +1,83 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+
4
+ require 'doeskeyvalue'
5
+ require 'rails'
6
+ require 'active_record'
7
+
8
+ require 'doeskeyvalue/keys'
9
+ require 'doeskeyvalue/indexes'
10
+ require 'doeskeyvalue/util'
11
+
12
+
13
+ module DoesKeyValue
14
+
15
+ # Create a Rails Engine
16
+ class Engine < Rails::Engine
17
+ end
18
+
19
+ # Return the current working version from VERSION file:
20
+ def self.version
21
+ @@version ||= File.open(File.join(File.dirname(__FILE__), "..", "VERSION"), "r").read
22
+ end
23
+
24
+ # Exception Types for DoesKeyValue
25
+ class NoColumnNameSpecified < Exception
26
+ def initialize(msg="A class column name must be provided for storing key values in blob"); super(msg); end
27
+ end
28
+ class NoKeyNameSpecified < Exception
29
+ def initialize(msg="A key name must be provided to build a DoesKeyValue key"); super(msg); end
30
+ end
31
+ class NoKeyForThatIndex < Exception
32
+ def initialize(msg="A key must exist before an index can be applied to it"); super(msg); end
33
+ end
34
+ class KeyAndIndexOptionsMustBeHash < Exception
35
+ def initialize(msg="Options passed to declarations of keys and indexes must of class Hash"); super(msg); end
36
+ end
37
+ class KeyValueIndexTableDoesNotExist < Exception
38
+ def initialize(msg="DoesKeyValue requires an index table be generated to use key indexes. Use generator to generate migration"); super(msg); end
39
+ end
40
+
41
+ end # DoesKeyValue
42
+
43
+
44
+ module ActiveRecord
45
+ class Base
46
+
47
+ # Call this method within your class to establish key-value behavior and prep
48
+ # the internal structure that will hold the blob
49
+ def self.doeskeyvalue(column, opts={})
50
+ puts "DOES_KEY_VALUE: Turned on for AR Column:#{column}"
51
+ self.instance_eval do
52
+ extend DoesKeyValue::Keys
53
+ extend DoesKeyValue::Indexes
54
+
55
+ # Identify the AR text column holding our data and serialize it:
56
+ @@key_value_column = column.to_sym
57
+ cattr_accessor :key_value_column
58
+ serialize @@key_value_column, Hash
59
+ end
60
+
61
+ Array.class_eval do
62
+ include DoesKeyValue::Util::CondArray
63
+ end
64
+
65
+ instance_eval <<-EOS
66
+ def #{@@key_value_column}_key(key_name, opts={})
67
+ puts "DOES_KEY_VALUE: Inside defined method #{@@key_value_column}_key"
68
+ key_name = key_name.to_sym
69
+ declare_key(@@key_value_column, key_name, opts)
70
+ end
71
+
72
+ def #{@@key_value_column}_index(key_name, opts={})
73
+ puts "DOES_KEY_VALUE: Inside defined method #{@@key_value_column}_index"
74
+ key_name = key_name.to_sym
75
+ declare_index(@@key_value_column, key_name, opts)
76
+ end
77
+ EOS
78
+ puts "DOES_KEY_VALUE: key and index methods declared"
79
+ end
80
+
81
+
82
+ end # ActiveRecord::Base
83
+ end # ActiveRecord
@@ -0,0 +1,25 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+ #
4
+ # IndexTableGenerator -- generator for the Index database table
5
+
6
+ require 'rails/generators'
7
+ require 'rails/generators/migration'
8
+
9
+ class DoeskeyvalueGenerator < Rails::Generators::Base
10
+ include Rails::Generators::Migration
11
+ source_root File.expand_path('../templates', __FILE__)
12
+
13
+ def self.next_migration_number(path)
14
+ if ActiveRecord::Base.timestamped_migrations
15
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
16
+ else
17
+ "%.3d" % (current_migration_number(path) + 1)
18
+ end
19
+ end
20
+
21
+ def create_migration_file
22
+ migration_template 'create_key_value_index.rb', 'db/migrate/create_key_value_index.rb'
23
+ end
24
+
25
+ end
@@ -0,0 +1,30 @@
1
+ # AWEXOME LABS
2
+ # DoesKeyValue
3
+ #
4
+ # CreateKeyValueIndex -- generated migration template for key/value index table
5
+
6
+ class CreateKeyValueIndex < ActiveRecord::Migration
7
+ def self.up
8
+ create_table :key_value_index do |t|
9
+ # The key is a composite of the grouping and key name (e.g., "settings.user_id")
10
+ t.string :key_name
11
+
12
+ # The stored value is saved as varchar(255), which limits indexability slightly:
13
+ t.string :value
14
+
15
+ # Store details about the target object:
16
+ t.string :obj_type
17
+ t.integer :obj_id
18
+
19
+ # Track all touches:
20
+ t.timestamps
21
+ end
22
+
23
+ # Index is important here:
24
+ add_index :key_value_index, [:obj_type, :key_name, :value]
25
+ end
26
+
27
+ def self.down
28
+ drop_table :key_value_index
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: doeskeyvalue
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Awexome Labs
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-15 00:00:00 -05:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bundler
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.0
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: jeweler
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.5.2
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ description: 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.
39
+ email: gems@awexomelabs.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - LICENSE.txt
46
+ - README.rdoc
47
+ files:
48
+ - .document
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - LICENSE.txt
52
+ - README.rdoc
53
+ - Rakefile
54
+ - VERSION
55
+ - doeskeyvalue.gemspec
56
+ - lib/doeskeyvalue.rb
57
+ - lib/doeskeyvalue/indexes.rb
58
+ - lib/doeskeyvalue/keys.rb
59
+ - lib/doeskeyvalue/util.rb
60
+ - lib/generators/doeskeyvalue/doeskeyvalue_generator.rb
61
+ - lib/generators/doeskeyvalue/templates/create_key_value_index.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/awexome/doeskeyvalue
64
+ licenses:
65
+ - MIT
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: -2545379118669446342
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.5.2
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Add schema-less NoSQL-like key values to any ActiveRecord class
93
+ test_files: []
94
+