activerecord2-hstore 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activerecord2-hstore.gemspec
4
+ gemspec
5
+
6
+ gem "activerecord", "~> 2.3.0", :require => "active_record"
7
+ gem "activesupport", "~> 2.3.0", :require => "active_support"
data/README.markdown ADDED
@@ -0,0 +1,162 @@
1
+ activerecord2-hstore
2
+ ====================
3
+
4
+ What is this?
5
+ -------------
6
+ This is a gem that provides some very basic functionality for working with
7
+ Postgresql's Hstore columns in ActiveRecord 2.
8
+
9
+ Documentation about the Postgresql Hstore feature can be found
10
+ **[here](http://www.postgresql.org/docs/9.1/static/hstore.html)**.
11
+
12
+ Requirements (aka boring stuff)
13
+ -------------------------------
14
+ This gem requires:
15
+
16
+ * ActiveRecord and ActiveSupport 2.3.x
17
+ * pg gem
18
+ * rspec (for running tests, duh)
19
+ * Ruby (Tested on 1.8.7 MRI, 1.9.2, and REE)
20
+ * Postgresql (Tested on 9.1)
21
+
22
+ Setup (aka more boring stuff)
23
+ -----------------------------
24
+ Install the gem like you would normally install any gem.
25
+
26
+ Enable the hstore extension on the postgres database(s) you wish to use.
27
+ Ether by creating a migration in your project that runs this SQL statement
28
+ or manually running it directly in psql console...
29
+
30
+ CREATE EXTENSION IF NOT EXISTS hstore;
31
+
32
+ Instead of me trying to hack ActiveRecord to add an actual hstore column type,
33
+ and risk breaking the universe, just manually write a migration that adds a
34
+ hstore column to your table. Here, I'll even give you an example:
35
+
36
+ ALTER TABLE my_table ADD COLUMN some_field hstore;
37
+
38
+ I recommend you add an index to that column. Supported indexes are BTREE, HASH,
39
+ GIST, and GIN. I'll leave you to handle that on your own.
40
+
41
+ Usage (aka the stuff you care about)
42
+ ------------------------------------
43
+ Now that the boring stuff is out of the way, you need to tell your model that
44
+ you have a hstore column.
45
+
46
+ Assume you have the following table:
47
+
48
+ peeps
49
+ id: integer
50
+ name: string
51
+ infos: hstore
52
+
53
+ You can tell your model infos is a hstore column thusly...
54
+
55
+ class Peep < ActiveRecord::Base
56
+ hstore_column :infos
57
+ end
58
+
59
+ What does that one line get you?
60
+
61
+ * A getter that returns the hstore column as a hash...
62
+
63
+ @peep.infos
64
+ >> {"age" => "25", "haircolor" => "black", "height" => "5'3\"", "likes" => "Cuddling while watching TV"}
65
+
66
+ * A setter that takes a hash and converts it to a hstore string (or the method can just take a hstore string)
67
+
68
+ @peeps.infos = some_hash
69
+
70
+ * These name scopes:
71
+ * infos\_has\_key (takes a string)
72
+ * infos\_has\_all\_keys (takes a string or an array of strings)
73
+ * infos\_has\_any\_keys (takes a string or an array of strings)
74
+
75
+ So what about querying the data in that colum? Well, you can always use the
76
+ standard condisions key in ActiveRecord's find method and use the proper
77
+ syntax from the Postgresql documentation. But if you're like me and like
78
+ using searchlogic, that's not an option. So in the same line in your model,
79
+ you can specifiy some keys you'd want to filter by...
80
+
81
+ class Peep < ActiveRecord::Base
82
+ hstore_column :infos, [:age, :haircolor, :likes]
83
+ end
84
+
85
+ Passing in an array of hstore keys will give you the following named scopes
86
+ to play with...
87
+
88
+ * infos\_age\_eq
89
+ * infos\_age\_neq
90
+ * infos\_age\_eq\_any
91
+ * infos\_age\_neq\_any
92
+ * infos\_age\_like
93
+ * infos\_age\_beigns\_with
94
+ * infos\_age\_ends\_with
95
+ * (Repeat list for "haircolor" and "likes")
96
+
97
+ Which means you can then do...
98
+
99
+ Peep.infos_likes_eq("Cuddling while watching TV")
100
+ Peep.searchlogic(:infos_age_neq => "23")
101
+
102
+ But Wait, There's More!
103
+ -----------------------
104
+
105
+ The gem also adds a helper method to the Hash and String objects for converting
106
+ hashes to hstore strings and back again.
107
+
108
+ These methods were originally implemented in a gem by
109
+ [softa](https://github.com/softa/activerecord-postgres-hstore) to add hstore
110
+ to ActiveReocord 3 and tweaked slightly for this gem.
111
+
112
+ Converting a hash into a hstore string that can be used to direclty store data
113
+ in a query...
114
+
115
+ {"something something" => "something", :dark => "side"}.to_hstore
116
+ >> "\"something something\"=>something,dark=>side"
117
+
118
+ Converting a hstore string that is returned from the database into a hash so
119
+ you can actually do something with it...
120
+
121
+ "\"something something\"=>something,dark=>side".from_hstore
122
+ >> {"something something" => "something", "dark" => "side"}
123
+
124
+ Note that taking a string from hstore into a hash will produce a hash where its
125
+ keys and values are all strings.
126
+
127
+
128
+ Running Tests
129
+ -------------
130
+ For the tests to run, it's assumed there is a Postgres database called
131
+ activerecord2\_hstore\_test. The specs will create a test table and populate
132
+ it with data for you. If you want to use a different database, then edit
133
+ spec/hstore\_spec.rb to your liking.
134
+
135
+ Then just run...
136
+
137
+ rake spec
138
+
139
+ Background / Why make this? / Me Rambling
140
+ -----------------------------------------
141
+ At my current employor, I'm helping to support a rather large Rails 2.3 app
142
+ (that unfortunatly will be stuck in 2.3 for quite some time) that runs on
143
+ Postgresql. The app's primary purpose is reporting on data from its data
144
+ warehouse of well... data. Because it's on Postgresql, the development team
145
+ was interested in using some of Postgresql's special features such as array
146
+ columns and hstore datatypes. We need the ability to easily take a hash
147
+ and store that as a hstore and read the column out as a hash. Also because
148
+ we're big on reporting and use searchlogic for filtering out data, we need
149
+ some way to search a hstore field for key with certain values.
150
+
151
+ To accomplish the first goal, I first needed a way to convert a Postgresql
152
+ hstore string into a Ruby hash and back to a string. I'm using the hash and
153
+ string methods from **[softa's gem](https://github.com/softa/activerecord-postgres-hstore)**
154
+ that provides hstore support for ActiveRecord 3. With those methods, I created
155
+ a way for you to tell ActiveRecord what columns are hstore columns and this
156
+ gem will override the default column getter method to return a hash and the
157
+ setter method to accept a hash which it then converts into a hstore string.
158
+
159
+ Part two of this gem is determining a way to query a hstore field. I decided
160
+ to have the gem generate searchlogic-like named scopes by sepcifying in the
161
+ model what keys in the hstore column you'll want to filter on. The gem will
162
+ create scopes in the style of "mycolumn\_key\_eq", "mycolumn\_key\_like", etc.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "activerecord2-hstore/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "activerecord2-hstore"
7
+ s.version = Activerecord2::Hstore::VERSION
8
+ s.authors = ["Tony Drake"]
9
+ s.email = ["t27duck@gmail.com"]
10
+ s.homepage = "https://github.com/t27duck/activerecord2-hstore"
11
+ s.summary = %q{Some basic support to help integrate Postgresql's HStore into a Rails 2.3 app}
12
+ s.description = %q{Allows you to mark a column in a model as a HStore column letting you pass in a hash for its setter and retrieve a hash from its getter method. Also provides a series to named scopes for easy querying of data.}
13
+
14
+ s.rubyforge_project = "activerecord2-hstore"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec", ">=2.0.0"
23
+ s.add_runtime_dependency "activerecord", "~> 2.3.0"
24
+ s.add_runtime_dependency "activesupport", "~> 2.3.0"
25
+ s.add_runtime_dependency "pg"
26
+ end
@@ -0,0 +1,24 @@
1
+ class Hash
2
+ # Generates an hstore string format. This is the format used to insert or update stuff in the database.
3
+ #
4
+ # Original implementation from:
5
+ # https://github.com/softa/activerecord-postgres-hstore/blob/master/lib/activerecord-postgres-hstore/hash.rb
6
+ def to_hstore
7
+ return "" if empty?
8
+
9
+ map { |key, value|
10
+ pair = [key, value].map { |element|
11
+ item = element.to_s.gsub(/"/, '\"')
12
+ if element.nil?
13
+ 'NULL'
14
+ elsif item =~ /[,\s=>]/ || item.blank?
15
+ '"%s"' % item
16
+ else
17
+ item
18
+ end
19
+ }
20
+
21
+ "%s=>%s" % pair
22
+ } * ","
23
+ end
24
+ end
@@ -0,0 +1,78 @@
1
+ module Hstore
2
+ module ActiveRecord
3
+ # Called when included in ActiveRecord. Extends the Extensions module.
4
+ def self.included(base)
5
+ base.extend Extensions
6
+ end
7
+
8
+ module Extensions
9
+ # Creates a series of methods and named scopes for a hstore column. This is the primary
10
+ # method you should use to invoke this gem in a model.
11
+ #
12
+ # USAGE IN A MODEL:
13
+ # class Foo < ActiveRecord::Base
14
+ # hstore_column :some_column, [:array_of_possible_keys, :you_may_want, :to_query_on]
15
+ # end
16
+ def hstore_column(column, keys=[])
17
+ create_getter_and_setter(column)
18
+ create_hstore_key_availability_scopes(column)
19
+ Array(keys).each{ |key| create_hstore_key_search_scopes(column, key) }
20
+ end
21
+
22
+ # Creates and overrides ActiveRecord's getter and setter methods for the hstore column.
23
+ # The getter returns a hash. The setter accepts and converts either a hash or a valid
24
+ # hstore string.
25
+ def create_getter_and_setter(column)
26
+ define_method column.to_sym do
27
+ read_attribute(column.to_sym).to_s.from_hstore
28
+ end
29
+
30
+ define_method "#{column}=".to_sym do |value|
31
+ value = value.is_a?(String) ? value : value.to_hstore
32
+ write_attribute(column.to_sym, value)
33
+ end
34
+ end
35
+
36
+ # Creates named scopes for the hstore column allowing you to determine if the column
37
+ # contains a given key or set of keys.
38
+ def create_hstore_key_availability_scopes(column)
39
+ named_scope "#{column}_has_key".to_sym, Proc.new{ |key|
40
+ { :conditions => ["#{column} ? :key", {:key => key}] }
41
+ }
42
+ named_scope "#{column}_has_all_keys".to_sym, Proc.new{ |keys|
43
+ { :conditions => ["#{column} ?& ARRAY[:keys]", {:keys => Array(keys)}] }
44
+ }
45
+ named_scope "#{column}_has_any_key".to_sym, Proc.new{ |keys|
46
+ { :conditions => ["#{column} ?| ARRAY[:keys]", {:keys => Array(keys)}] }
47
+ }
48
+ end
49
+
50
+ # Creates a slew of searchlogic-like named scopes to query for a key on a hstore column
51
+ def create_hstore_key_search_scopes(column, key)
52
+ named_scope "#{column}_#{key}_eq".to_sym, Proc.new{ |value|
53
+ { :conditions => ["#{column} -> '#{key}' = ?", value.to_s] }
54
+ }
55
+ named_scope "#{column}_#{key}_neq".to_sym, Proc.new{ |value|
56
+ { :conditions => ["#{column} -> '#{key}' != ?", value.to_s] }
57
+ }
58
+ named_scope "#{column}_#{key}_eq_any".to_sym, Proc.new{ |value|
59
+ { :conditions => ["#{column} -> '#{key}' IN(?)", value.map{|v| v.to_s} ] }
60
+ }
61
+ named_scope "#{column}_#{key}_neq_any".to_sym, Proc.new{ |value|
62
+ { :conditions => ["#{column} -> '#{key}' NOT IN(?)", value.map{|v| v.to_s} ] }
63
+ }
64
+ named_scope "#{column}_#{key}_like".to_sym, Proc.new{ |value|
65
+ { :conditions => ["#{column} -> '#{key}' ILIKE(?)", "%#{value.to_s}%"] }
66
+ }
67
+ named_scope "#{column}_#{key}_begins_with".to_sym, Proc.new{ |value|
68
+ { :conditions => ["#{column} -> '#{key}' ILIKE(?)", "#{value.to_s}%"] }
69
+ }
70
+ named_scope "#{column}_#{key}_ends_with".to_sym, Proc.new{ |value|
71
+ { :conditions => ["#{column} -> '#{key}' ILIKE(?)", "%#{value.to_s}"] }
72
+ }
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+
@@ -0,0 +1,24 @@
1
+ class String
2
+ # Generates a hash from an hstore string format.
3
+ #
4
+ # Original implementation from:
5
+ # https://github.com/softa/activerecord-postgres-hstore/blob/master/lib/activerecord-postgres-hstore/string.rb
6
+ def from_hstore
7
+ quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
8
+ unquoted_string = /[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
9
+ string = /(#{quoted_string}|#{unquoted_string})/
10
+ hstore_pair = /#{string}\s*=>\s*#{string}/
11
+
12
+ token_pairs = (scan(hstore_pair)).map { |key, value| [key, value =~ /^NULL$/i ? nil : value] }
13
+ token_pairs = token_pairs.map { |key, value|
14
+ [key, value].map { |element|
15
+ case element
16
+ when nil then element
17
+ when /^"(.*)"$/ then $1.gsub(/\\(.)/, '\1')
18
+ else element.gsub(/\\(.)/, '\1')
19
+ end
20
+ }
21
+ }
22
+ Hash[ token_pairs ]
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ module Activerecord2
2
+ module Hstore
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ require "activerecord2-hstore/version"
2
+ require "activerecord2-hstore/string"
3
+ require "activerecord2-hstore/hash"
4
+ require "activerecord2-hstore/hstore"
5
+
6
+ module Activerecord2
7
+ module Hstore
8
+ # Your code goes here...
9
+ end
10
+ end
11
+
12
+ ActiveRecord::Base.send(:include, Hstore::ActiveRecord)
data/spec/hash_spec.rb ADDED
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe Hash do
4
+ describe "Converting a hash to a hstore string" do
5
+ it "#to_hstore" do
6
+ {:a=>"b"}.to_hstore.should == "a=>b"
7
+ {"a"=>"b"}.to_hstore.should == "a=>b"
8
+ {:a=>:b}.to_hstore.should == "a=>b"
9
+ {"a"=>"2"}.to_hstore.should == "a=>2"
10
+ {:a=>2}.to_hstore.should == "a=>2"
11
+ {2=>2}.to_hstore.should == "2=>2"
12
+ {"a b"=>"b"}.to_hstore.should == "\"a b\"=>b"
13
+ {"a b"=>"b c"}.to_hstore.should == "\"a b\"=>\"b c\""
14
+ {"a"=>"b c"}.to_hstore.should == "a=>\"b c\""
15
+ end
16
+
17
+ it "converts a multiball hash to a hstore string" do
18
+ all_should_match({"a"=>"b", "c"=>"d"}, [/a=>b/, /c=>d/])
19
+ all_should_match({:a=>"b", "c"=>:d}, [/a=>b/, /c=>d/])
20
+ all_should_match({"a 1"=>"b 1", "c"=>"d"}, [/\"a 1\"=>\"b 1\"/, /c=>d/])
21
+ all_should_match({"a"=>"b", "c"=>"d 1"}, [/a=>b/, /c=>\"d 1\"/])
22
+ all_should_match({"a"=>"b", "c 1"=>"d"}, [/a=>b/, /\"c 1\"=>d/])
23
+ all_should_match({:a=>:b, "c 1"=>:"d 1"}, [/a=>b/, /\"c 1\"=>\"d 1\"/])
24
+ all_should_match({"a"=>"b", :c=>:d, "e 1"=>"f 1"}, [/a=>b/, /c=>d/, /\"e 1\"=>\"f 1\"/])
25
+ end
26
+
27
+ def all_should_match(hash, expects)
28
+ expects.each do |e|
29
+ hash.to_hstore.should match(e)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,179 @@
1
+ require "spec_helper"
2
+
3
+ ActiveRecord::Base.establish_connection(
4
+ :adapter => "postgresql",
5
+ :database => "activerecord2_hstore_test",
6
+ :encoding => "unicode"
7
+ )
8
+
9
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS my_hstores")
10
+ ActiveRecord::Base.connection.create_table(:my_hstores) do |t|
11
+ t.string :label
12
+ end
13
+ ActiveRecord::Base.connection.execute("CREATE EXTENSION IF NOT EXISTS hstore")
14
+ ActiveRecord::Base.connection.execute("ALTER TABLE my_hstores ADD COLUMN some_field hstore")
15
+
16
+ class MyHstore < ActiveRecord::Base
17
+ hstore_column :some_field, [:key]
18
+ end
19
+
20
+ describe Hstore do
21
+ before(:each) do
22
+ ActiveRecord::Base.connection.increment_open_transactions
23
+ ActiveRecord::Base.connection.begin_db_transaction
24
+ end
25
+
26
+ after(:each) do
27
+ ActiveRecord::Base.connection.rollback_db_transaction
28
+ ActiveRecord::Base.connection.decrement_open_transactions
29
+ end
30
+
31
+ it "creates the correct named scopes" do
32
+ %w(eq neq eq_any neq_any like begins_with ends_with).each do |predicate|
33
+ MyHstore.should respond_to("some_field_key_#{predicate}")
34
+ end
35
+ end
36
+
37
+ describe "available methods" do
38
+ let(:subject) do
39
+ MyHstore.new
40
+ end
41
+
42
+ it "creates a getter and setter for the some_field" do
43
+ subject.should respond_to(:some_field)
44
+ subject.should respond_to(:some_field=)
45
+ end
46
+
47
+ it "uses ActiveRecord's read_attribute for the getter method" do
48
+ subject.should_receive(:read_attribute).with(:some_field).and_return("a=>b")
49
+ subject.some_field
50
+ end
51
+
52
+ describe "setter method" do
53
+ it "uses ActiveRecord's write_attribute" do
54
+ subject.should_receive(:write_attribute)
55
+ subject.some_field = {:a => :b}
56
+ end
57
+
58
+ it "can also accept a hstore string instead of a hash" do
59
+ subject.stub(:write_attribute)
60
+ subject.some_field = "a=>b"
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "querying data" do
66
+ before(:each) do
67
+ MyHstore.create( :label=> "A", :some_field => {"key" => "1"}.to_hstore )
68
+ MyHstore.create( :label=> "B", :some_field => {:key => 1, "a" => "b"}.to_hstore )
69
+ MyHstore.create( :label=> "C", :some_field => {"key" => "2"}.to_hstore )
70
+ MyHstore.create( :label=> "D", :some_field => {"key" => "3"}.to_hstore )
71
+ MyHstore.create( :label=> "E", :some_field => {"key" => "123456789"}.to_hstore )
72
+ MyHstore.create( :label=> "F", :some_field => {"c" => "x"}.to_hstore )
73
+ end
74
+
75
+ it "queries for the records containing a specific key" do
76
+ result = MyHstore.some_field_has_key("a")
77
+ result.map(&:label).should include "B"
78
+ %w(A C D E F).each do |key|
79
+ result.map(&:label).should_not include key
80
+ end
81
+ end
82
+
83
+ it "queries for the records containing a set keys" do
84
+ result = MyHstore.some_field_has_all_keys(["a", "key"])
85
+ result.map(&:label).should include "B"
86
+ %w(A C D E F).each do |key|
87
+ result.map(&:label).should_not include key
88
+ end
89
+
90
+ result = MyHstore.some_field_has_all_keys("a")
91
+ result.map(&:label).should include "B"
92
+ %w(A C D E F).each do |key|
93
+ result.map(&:label).should_not include key
94
+ end
95
+ end
96
+
97
+ it "queries for the records containing any set keys" do
98
+ result = MyHstore.some_field_has_any_key(["a", "c"])
99
+ %w(B F).each do |key|
100
+ result.map(&:label).should include key
101
+ end
102
+ %w(A C D E).each do |key|
103
+ result.map(&:label).should_not include key
104
+ end
105
+
106
+ result = MyHstore.some_field_has_any_key("a")
107
+ result.map(&:label).should include "B"
108
+ %w(A C D E F).each do |key|
109
+ result.map(&:label).should_not include key
110
+ end
111
+ end
112
+
113
+ it "queries the right data for the named scope *_eq" do
114
+ result = MyHstore.some_field_key_eq("1")
115
+ %w(A B).each do |key|
116
+ result.map(&:label).should include key
117
+ end
118
+ %w(C D E F).each do |key|
119
+ result.map(&:label).should_not include key
120
+ end
121
+ end
122
+
123
+ it "queries the right data for the named scope *_neq" do
124
+ result = MyHstore.some_field_key_neq("1")
125
+ %w(A B F).each do |key|
126
+ result.map(&:label).should_not include key
127
+ end
128
+ %w(C D E).each do |key|
129
+ result.map(&:label).should include key
130
+ end
131
+ end
132
+
133
+ it "queries the right data for the named scope *_eq_any" do
134
+ result = MyHstore.some_field_key_eq_any(["2", "3"])
135
+ %w(A B E F).each do |key|
136
+ result.map(&:label).should_not include key
137
+ end
138
+ %w(C D).each do |key|
139
+ result.map(&:label).should include key
140
+ end
141
+ end
142
+
143
+ it "queries the right data for the named scope *_neq_any" do
144
+ result = MyHstore.some_field_key_neq_any(["2", "3"])
145
+ %w(A B E).each do |key|
146
+ result.map(&:label).should include key
147
+ end
148
+ %w(C D F).each do |key|
149
+ result.map(&:label).should_not include key
150
+ end
151
+ end
152
+
153
+ it "queries the right data for the named scope *_like" do
154
+ result = MyHstore.some_field_key_like("456")
155
+ result.map(&:label).should include "E"
156
+ %w(A B C D F).each do |key|
157
+ result.map(&:label).should_not include key
158
+ end
159
+ end
160
+
161
+ it "queries the right data for the named scope *_begins_with" do
162
+ result = MyHstore.some_field_key_begins_with("123")
163
+ result.map(&:label).should include "E"
164
+ %w(A B C D F).each do |key|
165
+ result.map(&:label).should_not include key
166
+ end
167
+ end
168
+
169
+ it "queries the right data for the named scope *_ends_with" do
170
+ result = MyHstore.some_field_key_ends_with("789")
171
+ result.map(&:label).should include "E"
172
+ %w(A B C D F).each do |key|
173
+ result.map(&:label).should_not include key
174
+ end
175
+ end
176
+
177
+ end
178
+
179
+ end
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require "active_support"
5
+ require "active_record"
6
+ require "activerecord2-hstore"
7
+
8
+ RSpec.configure do |config|
9
+ # some (optional) config here
10
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe String do
4
+ describe "#from_hstore" do
5
+ it "handles a single key value pair" do
6
+ "a=>b".from_hstore.should == {"a" => "b"}
7
+ "\"a\"=>\"b\"".from_hstore.should == {"a" => "b"}
8
+ "\"a 1\"=>b".from_hstore.should == {"a 1" => "b"}
9
+ "\"a 1\"=>\"b 1\"".from_hstore.should == {"a 1" => "b 1"}
10
+ "1=>b".from_hstore.should == {"1" => "b"}
11
+ "1=>1".from_hstore.should == {"1" => "1"}
12
+ end
13
+
14
+ it "converts a multikeyed hstore string to a hash" do
15
+ "a=>b,c=>d".from_hstore.should == {"a" => "b", "c" => "d"}
16
+ "\"a\"=>\"b\",\"c\"=>\"d\"".from_hstore.should == {"a" => "b", "c" => "d"}
17
+ "\"a 1\"=>b,c=>d".from_hstore.should == {"a 1" => "b", "c" => "d"}
18
+ "\"a 1\"=>b,c=>\"d 1\"".from_hstore.should == {"a 1" => "b", "c" => "d 1"}
19
+ "\"a 1\"=>\"b 1\",c=>\"d 1\"".from_hstore.should == {"a 1" => "b 1", "c" => "d 1"}
20
+ "1=>b,c=>\"d 1\"".from_hstore.should == {"1" => "b", "c" => "d 1"}
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord2-hstore
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Tony Drake
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-02-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 15
29
+ segments:
30
+ - 2
31
+ - 0
32
+ - 0
33
+ version: 2.0.0
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: activerecord
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 2
47
+ - 3
48
+ - 0
49
+ version: 2.3.0
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: activesupport
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 2
63
+ - 3
64
+ - 0
65
+ version: 2.3.0
66
+ type: :runtime
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: pg
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ type: :runtime
81
+ version_requirements: *id004
82
+ description: Allows you to mark a column in a model as a HStore column letting you pass in a hash for its setter and retrieve a hash from its getter method. Also provides a series to named scopes for easy querying of data.
83
+ email:
84
+ - t27duck@gmail.com
85
+ executables: []
86
+
87
+ extensions: []
88
+
89
+ extra_rdoc_files: []
90
+
91
+ files:
92
+ - .gitignore
93
+ - .rspec
94
+ - Gemfile
95
+ - README.markdown
96
+ - Rakefile
97
+ - activerecord2-hstore.gemspec
98
+ - lib/activerecord2-hstore.rb
99
+ - lib/activerecord2-hstore/hash.rb
100
+ - lib/activerecord2-hstore/hstore.rb
101
+ - lib/activerecord2-hstore/string.rb
102
+ - lib/activerecord2-hstore/version.rb
103
+ - spec/hash_spec.rb
104
+ - spec/hstore_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/string_spec.rb
107
+ homepage: https://github.com/t27duck/activerecord2-hstore
108
+ licenses: []
109
+
110
+ post_install_message:
111
+ rdoc_options: []
112
+
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ requirements: []
134
+
135
+ rubyforge_project: activerecord2-hstore
136
+ rubygems_version: 1.8.10
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: Some basic support to help integrate Postgresql's HStore into a Rails 2.3 app
140
+ test_files:
141
+ - spec/hash_spec.rb
142
+ - spec/hstore_spec.rb
143
+ - spec/spec_helper.rb
144
+ - spec/string_spec.rb