activerecord-postgres-hstore 0.0.1 → 0.0.2

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/README.textile CHANGED
@@ -1,4 +1,4 @@
1
- .h2 Goodbye serialize, hello hstore.
1
+ h2. Goodbye serialize, hello hstore.
2
2
 
3
3
  You need dynamic columns in your tables. What do you do?
4
4
 
@@ -18,83 +18,113 @@ You need dynamic columns in your tables. What do you do?
18
18
  |count all with negative condition|18722,149|1677,948|SELECT count(*) FROM foos WHERE data !~ 'another key: 9999990';|SELECT count(*) FROM bars WHERE not data @> '"another key"=>9999990';|
19
19
  |find one with condition|17740,307|130,227|SELECT count(*) FROM foos WHERE data ~ 'another key: 9999990';|SELECT * FROM bars WHERE data @> '"another key"=>9999990'|
20
20
 
21
- Benchmarks made in my local machine, time in milliseconds.
21
+ Benchmarks made in my local machine, with a million records. Time is in milliseconds.
22
22
 
23
- .h2 Requirements
23
+ h2. Requirements
24
24
 
25
25
  Postgresql 8.4 with contrib and Rails 3. (It might work on 2.3.x with minor patches...)
26
26
 
27
- .h2 Install
27
+ In Ubuntu, this is easy:
28
+
29
+ @sudo apt-get install postgresql-8.4 postgresql-contrib-8.4@
30
+
31
+ In Mac ...you are screwed. Use a VM.
32
+
33
+ h2. Install
28
34
 
29
35
  Hstore is a postgres contrib type. Check it out first:
30
36
 
31
- http://www.postgresql.org/docs/8.4/static/hstore.html
37
+ "http://www.postgresql.org/docs/8.4/static/hstore.html":http://www.postgresql.org/docs/8.4/static/hstore.html
32
38
 
33
39
  Then, just add this to your Gemfile:
34
40
 
35
- gem 'activerecord-postgres-hstore'
41
+ @gem 'activerecord-postgres-hstore'@
36
42
 
37
43
  And run your bundler:
38
44
 
39
- bundle install
45
+ @bundle install@
40
46
 
41
47
  Now you need to create a migration that adds hstore support for your postgresql database:
42
48
 
43
- rails g railtie:hstore
49
+ @rails g railtie:hstore@
44
50
 
45
51
  Run it:
46
52
 
47
- rake db:migrate
53
+ @rake db:migrate@
48
54
 
49
55
  Finally you can create your own tables using hstore type. It's easy:
50
56
 
51
- rails g model Person name:string data:hstore
57
+ @rails g model Person name:string data:hstore@
52
58
 
53
59
  You're done.
54
60
 
55
61
  Well, not yet. Don't forget to add indexes. Like this:
56
62
 
57
- CREATE INDEX people_gist_data ON people USING GIST(data);
58
- -- or
59
- CREATE INDEX people_gin_data ON people USING GIN(data);
63
+ @CREATE INDEX people_gist_data ON people USING GIST(data);@
64
+ or
65
+ @CREATE INDEX people_gin_data ON people USING GIN(data);@
60
66
 
61
67
  To my experience GIN is faster for searching records.
62
68
 
63
- .h2 Usage
69
+ h2. Usage
64
70
 
65
71
  Once you have it installed, you just need to learn a little bit of new sqls for selecting stuff (creting and updating is transparent).
66
72
 
67
73
  Find records that contains a key named 'foo':
68
74
 
69
- Person.where("data ? 'foo'")
75
+ @Person.where("data ? 'foo'")@
70
76
 
71
77
  Find records where 'foo' is equal to 'bar':
72
78
 
73
- Person.where("data -> 'foo' = 'bar'")
79
+ @Person.where("data -> 'foo' = 'bar'")@
74
80
 
75
81
  This same sql is at least twice as fast (using indexes) if you do it that way:
76
82
 
77
- Person.where("data @> 'foo=>bar'")
83
+ @Person.where("data @> 'foo=>bar'")@
78
84
 
79
85
  Find records where 'foo' is not equal to 'bar':
80
86
 
81
- Person.where("data -> 'foo' <> 'bar'")
82
- # or
83
- Person.where("not data @> 'foo=>bar'")
87
+ @Person.where("data -> 'foo' <> 'bar'")@
88
+ or
89
+ @Person.where("not data @> 'foo=>bar'")@
84
90
 
85
91
  Find records where 'foo' is like 'bar':
86
92
 
87
- Person.where("data -> 'foo' LIKE '%bar%'")
88
- # or something like ...
89
- Person.where("data -> 'foo' ILIKE '%bar%'")
93
+ @Person.where("data -> 'foo' LIKE '%bar%'")@
94
+ or something like ...
95
+ @Person.where("data -> 'foo' ILIKE '%bar%'")@
96
+
97
+ If you need to delete a key in a record, you can do it that way:
98
+
99
+ @person.destroy_key(:data, :foo)@
100
+
101
+ This way you'll also save the record:
102
+
103
+ @person.destroy_key!(:data, :foo)@
104
+
105
+ The destroy_key method returns 'self', so you can chain it:
106
+
107
+ @person.destroy_key(:data, :foo).destroy_key(:data, :bar).save@
108
+
109
+ But there it a shortcut for that:
110
+
111
+ @person.destroy_keys(:data, :foo, :bar)@
112
+
113
+ or...
114
+
115
+ @person.destroy_keys!(:data, :foo, :bar)@
116
+
117
+ And finally, if you need to delete keys in many rows, you can:
118
+
119
+
90
120
 
91
121
  Have fun.
92
122
 
93
- .h2 Help
123
+ h2. Help
94
124
 
95
125
  You can use issues in github for that. Or else you can reach me at twitter: @joaomilho
96
126
 
97
- .h2 Note on Patches/Pull Requests
127
+ h2. Note on Patches/Pull Requests
98
128
 
99
129
  * Fork the project.
100
130
  * Make your feature addition or bug fix.
@@ -104,6 +134,6 @@ You can use issues in github for that. Or else you can reach me at twitter: @joa
104
134
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
105
135
  * Send me a pull request. Bonus points for topic branches.
106
136
 
107
- .h2 Copyright
137
+ h2. Copyright
108
138
 
109
139
  Copyright (c) 2010 Juan Maiz. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -1,6 +1,51 @@
1
1
  # ActiveRecord::ConnectionAdapters::PostgreSQLColumn.new('data','','hstore').type
2
2
  module ActiveRecord
3
3
  class Base
4
+ def self.delete_key attribute, key
5
+ #UPDATE tab SET h = delete(h, 'k1');
6
+ unless column_names.include?(attribute.to_s)
7
+ raise "invalid attribute #{attribute}"
8
+ end
9
+ update_all(["#{attribute} = delete(#{attribute},?)",key])
10
+ end
11
+ def self.delete_keys attribute, *keys
12
+ unless column_names.include?(attribute.to_s)
13
+ raise "invalid attribute #{attribute}"
14
+ end
15
+ delete_str = "delete(#{attribute},?)"
16
+ (keys.count-1).times do
17
+ delete_str = "delete(#{delete_str},?)"
18
+ end
19
+ update_all(["#{attribute} = #{delete_str}", *keys])
20
+ end
21
+
22
+ def destroy_key attribute, key
23
+ unless self.class.column_names.include?(attribute.to_s)
24
+ raise "invalid attribute #{attribute}"
25
+ end
26
+ new_value = send(attribute)
27
+ new_value.delete(key.to_s)
28
+ send("#{attribute}=", new_value)
29
+ self
30
+ end
31
+ def destroy_key! attribute, key
32
+ destroy_key(attribute, key).save
33
+ end
34
+ def destroy_keys attribute, *keys
35
+ for key in keys
36
+ new_value = send(attribute)
37
+ new_value.delete(key.to_s)
38
+ send("#{attribute}=", new_value)
39
+ end
40
+ self
41
+ end
42
+ def destroy_keys! attribute, *keys
43
+ unless self.class.column_names.include?(attribute.to_s)
44
+ raise "invalid attribute #{attribute}"
45
+ end
46
+ destroy_keys(attribute, *keys).save
47
+ end
48
+
4
49
  # For Rails 3 compat :D
5
50
  #alias :old_arel_attributes_values :arel_attributes_values
6
51
  def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
@@ -1,6 +1,7 @@
1
1
  class Hash
2
2
 
3
3
  def to_hstore
4
+ return "''" if empty?
4
5
  #@todo DIOGO! Check security issues with this quoting pleaz
5
6
  map{|idx,val| "('#{idx}'=>'#{val.to_s.gsub(/'/,"''")}')" }.join(' || ')
6
7
  end
@@ -5,6 +5,7 @@ class String
5
5
  end
6
6
 
7
7
  def valid_hstore?
8
+ return true if empty? || self == "''"
8
9
  # This is what comes from the database
9
10
  dbl_quotes_re = /"([^"]+)"=>"([^"]+)"/
10
11
  # TODO
@@ -1,39 +1,24 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "ActiverecordPostgresHstore" do
4
- it "should convert hstore string to hash" do
4
+ it "should convert hash to hstore string" do
5
5
  {:a => 1, :b => 2}.to_hstore.should == "('a'=>'1') || ('b'=>'2')"
6
6
  end
7
7
 
8
- it "should convert hash to hstore string" do
8
+ it "should convert hstore string to hash" do
9
9
  '"a"=>"1", "b"=>"2"'.from_hstore.should == {'a' => '1', 'b' => '2'}
10
10
  end
11
11
 
12
12
  it "should quote correctly" do
13
13
  {:a => "'a'"}.to_hstore.should == "('a'=>'''a''')"
14
14
  end
15
-
16
- end
17
-
18
- =begin
19
15
 
20
- #---
21
-
22
- test "should create contact" do
23
- assert Contact.make :dynamic_values => {:a => 1, :b => 2}
24
- end
25
-
26
- test "should raise HstoreTypeMismatch" do
27
- assert_raises ActiveRecord::HstoreTypeMismatch do
28
- assert Contact.make :dynamic_values => "bug"
29
- end
16
+ it "should convert empty hash" do
17
+ {}.to_hstore.should == "''"
30
18
  end
31
19
 
32
- test "should read values from contact" do
33
- contact = Contact.make :dynamic_values => {:a => 1, :b => "Lorem ipsum", 'other stuff' => "'''a'''"}
34
- assert_equal({'a' => '1', 'b' => 'Lorem ipsum', 'other stuff' => "'''a'''"}, Contact.find(contact.id).dynamic_values)
20
+ it "should convert empty string" do
21
+ ''.from_hstore.should == {}
35
22
  end
36
-
23
+
37
24
  end
38
-
39
- =end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-postgres-hstore
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 27
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 1
9
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
10
11
  platform: ruby
11
12
  authors:
12
13
  - Juan Maiz
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-08 00:00:00 -03:00
18
+ date: 2010-09-09 00:00:00 -03:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rspec
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 13
27
30
  segments:
28
31
  - 1
29
32
  - 2
@@ -54,6 +57,7 @@ files:
54
57
  - lib/templates/setup_hstore.rb
55
58
  - spec/activerecord-postgres-hstore_spec.rb
56
59
  - README.textile
60
+ - spec/spec_helper.rb
57
61
  has_rdoc: true
58
62
  homepage: http://github.com/softa/activerecord-postgres-hstore
59
63
  licenses: []
@@ -64,26 +68,30 @@ rdoc_options:
64
68
  require_paths:
65
69
  - lib
66
70
  required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
67
72
  requirements:
68
73
  - - ">="
69
74
  - !ruby/object:Gem::Version
75
+ hash: 3
70
76
  segments:
71
77
  - 0
72
78
  version: "0"
73
79
  required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
74
81
  requirements:
75
82
  - - ">="
76
83
  - !ruby/object:Gem::Version
84
+ hash: 3
77
85
  segments:
78
86
  - 0
79
87
  version: "0"
80
88
  requirements: []
81
89
 
82
90
  rubyforge_project:
83
- rubygems_version: 1.3.6
91
+ rubygems_version: 1.3.7
84
92
  signing_key:
85
93
  specification_version: 3
86
94
  summary: Goodbye serialize, hello hstore
87
95
  test_files:
88
- - spec/spec_helper.rb
89
96
  - spec/activerecord-postgres-hstore_spec.rb
97
+ - spec/spec_helper.rb