activerecord-postgres-hstore-core 0.0.3
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 +8 -0
- data/Gemfile +3 -0
- data/Rakefile +13 -0
- data/activerecord-postgres-hstore-core.gemspec +26 -0
- data/lib/activerecord-postgres-hstore-core.rb +9 -0
- data/lib/activerecord-postgres-hstore-core/version.rb +3 -0
- data/lib/activerecord_postgres_hstore_core/activerecord.rb +150 -0
- data/lib/activerecord_postgres_hstore_core/hash.rb +39 -0
- data/lib/activerecord_postgres_hstore_core/string.rb +43 -0
- data/rails/init.rb +1 -0
- data/spec/activerecord_postgres_hstore_core/activerecord_posgres_hstore_database_spec.rb +48 -0
- data/spec/activerecord_postgres_hstore_core/activerecord_postgres_hstore_datatype_spec.rb +96 -0
- data/spec/database.yml.sample +7 -0
- data/spec/models.rb +5 -0
- data/spec/schema.rb +14 -0
- data/spec/spec_helper.rb +61 -0
- metadata +172 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup :default, :development
|
4
|
+
|
5
|
+
desc 'Default: run specs'
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.pattern = "spec/**/*_spec.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$:.push File.dirname(__FILE__) + '/lib'
|
2
|
+
require 'activerecord-postgres-hstore-core/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = %q{activerecord-postgres-hstore-core}
|
6
|
+
gem.authors = ["Jt Gleason"]
|
7
|
+
gem.date = %q{2012-02-29}
|
8
|
+
gem.description = %q{Allows you to use active record with databases that already have an hstore type}
|
9
|
+
gem.summary = "Hstore AR for Hstore DB"
|
10
|
+
gem.email = %q{jt@twitch.tv}
|
11
|
+
gem.homepage = ''
|
12
|
+
|
13
|
+
gem.add_dependency 'rails', '~> 3.0'
|
14
|
+
gem.add_development_dependency 'rspec', '~> 2.6'
|
15
|
+
gem.add_development_dependency 'ammeter', '~> 0.1.3'
|
16
|
+
gem.add_development_dependency 'pg'
|
17
|
+
gem.add_development_dependency 'guard'
|
18
|
+
gem.add_development_dependency 'guard-rspec'
|
19
|
+
|
20
|
+
|
21
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
gem.files = `git ls-files`.split("\n")
|
23
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
gem.require_paths = ['lib']
|
25
|
+
gem.version = ActiveRecordPostgresHstore::VERSION
|
26
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
2
|
+
# Extends AR to add Hstore functionality.
|
3
|
+
module ActiveRecord
|
4
|
+
|
5
|
+
# Adds methods for deleting keys in your hstore columns
|
6
|
+
class Base
|
7
|
+
|
8
|
+
# Deletes all keys from a specific column in a model. E.g.
|
9
|
+
# Person.delete_key(:info, :father)
|
10
|
+
# The SQL generated will be:
|
11
|
+
# UPDATE "people" SET "info" = delete("info",'father');
|
12
|
+
def self.delete_key attribute, key
|
13
|
+
raise "invalid attribute #{attribute}" unless column_names.include?(attribute.to_s)
|
14
|
+
update_all([%(#{attribute} = delete("#{attribute}",?)),key])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Deletes many keys from a specific column in a model. E.g.
|
18
|
+
# Person.delete_key(:info, :father, :mother)
|
19
|
+
# The SQL generated will be:
|
20
|
+
# UPDATE "people" SET "info" = delete(delete("info",'father'),'mother');
|
21
|
+
def self.delete_keys attribute, *keys
|
22
|
+
raise "invalid attribute #{attribute}" unless column_names.include?(attribute.to_s)
|
23
|
+
delete_str = "delete(#{attribute},?)"
|
24
|
+
(keys.count-1).times{ delete_str = "delete(#{delete_str},?)" }
|
25
|
+
update_all(["#{attribute} = #{delete_str}", *keys])
|
26
|
+
end
|
27
|
+
|
28
|
+
# Deletes a key in a record. E.g.
|
29
|
+
# witt = Person.find_by_name("Ludwig Wittgenstein")
|
30
|
+
# witt.destroy_key(:info, :father)
|
31
|
+
# It does not save the record, so you'll have to do it.
|
32
|
+
def destroy_key attribute, key
|
33
|
+
raise "invalid attribute #{attribute}" unless self.class.column_names.include?(attribute.to_s)
|
34
|
+
new_value = send(attribute)
|
35
|
+
new_value.delete(key.to_s)
|
36
|
+
send("#{attribute}=", new_value)
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Deletes a key in a record. E.g.
|
41
|
+
# witt = Person.find_by_name("Ludwig Wittgenstein")
|
42
|
+
# witt.destroy_key(:info, :father)
|
43
|
+
# It does save the record.
|
44
|
+
def destroy_key! attribute, key
|
45
|
+
destroy_key(attribute, key).save
|
46
|
+
end
|
47
|
+
|
48
|
+
# Deletes many keys in a record. E.g.
|
49
|
+
# witt = Person.find_by_name("Ludwig Wittgenstein")
|
50
|
+
# witt.destroy_keys(:info, :father, :mother)
|
51
|
+
# It does not save the record, so you'll have to do it.
|
52
|
+
def destroy_keys attribute, *keys
|
53
|
+
for key in keys
|
54
|
+
new_value = send(attribute)
|
55
|
+
new_value.delete(key.to_s)
|
56
|
+
send("#{attribute}=", new_value)
|
57
|
+
end
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Deletes many keys in a record. E.g.
|
62
|
+
# witt = Person.find_by_name("Ludwig Wittgenstein")
|
63
|
+
# witt.destroy_keys!(:info, :father, :mother)
|
64
|
+
# It does save the record.
|
65
|
+
def destroy_keys! attribute, *keys
|
66
|
+
raise "invalid attribute #{attribute}" unless self.class.column_names.include?(attribute.to_s)
|
67
|
+
destroy_keys(attribute, *keys).save
|
68
|
+
end
|
69
|
+
|
70
|
+
# This method is replaced for Rails 3 compatibility.
|
71
|
+
# All I do is add the condition when the field is a hash that converts the value
|
72
|
+
# to hstore format.
|
73
|
+
# IMHO this should be delegated to the column, so it won't be necessary to rewrite all
|
74
|
+
# this method.
|
75
|
+
def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
|
76
|
+
attrs = {}
|
77
|
+
attribute_names.each do |name|
|
78
|
+
if (column = column_for_attribute(name)) && (include_primary_key || !column.primary)
|
79
|
+
if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name))
|
80
|
+
value = read_attribute(name)
|
81
|
+
if self.class.columns_hash[name].type == :hstore && value && value.is_a?(Hash)
|
82
|
+
value = value.to_hstore # Done!
|
83
|
+
elsif value && self.class.serialized_attributes.has_key?(name) && (value.acts_like?(:date) || value.acts_like?(:time) || value.is_a?(Hash) || value.is_a?(Array))
|
84
|
+
value = value.to_yaml
|
85
|
+
end
|
86
|
+
attrs[self.class.arel_table[name]] = value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
attrs
|
91
|
+
end
|
92
|
+
end
|
93
|
+
# This erro class is used when the user passes a wrong value to a hstore column.
|
94
|
+
# Hstore columns accepts hashes or hstore valid strings. It is validated with
|
95
|
+
# String#valid_hstore? method.
|
96
|
+
class HstoreTypeMismatch < ActiveRecord::ActiveRecordError
|
97
|
+
end
|
98
|
+
|
99
|
+
module ConnectionAdapters
|
100
|
+
|
101
|
+
class TableDefinition
|
102
|
+
|
103
|
+
# Adds hstore type for migrations. So you can add columns to a table like:
|
104
|
+
# create_table :people do |t|
|
105
|
+
# ...
|
106
|
+
# t.hstore :info
|
107
|
+
# ...
|
108
|
+
# end
|
109
|
+
def hstore(*args)
|
110
|
+
options = args.extract_options!
|
111
|
+
column_names = args
|
112
|
+
column_names.each { |name| column(name, 'hstore', options) }
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
class PostgreSQLColumn < Column
|
118
|
+
# Does the type casting from hstore columns using String#from_hstore or Hash#from_hstore.
|
119
|
+
def type_cast_code_with_hstore(var_name)
|
120
|
+
type == :hstore ? "#{var_name}.from_hstore" : type_cast_code_without_hstore(var_name)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Adds the hstore type for the column.
|
124
|
+
def simplified_type_with_hstore(field_type)
|
125
|
+
field_type == 'hstore' ? :hstore : simplified_type_without_hstore(field_type)
|
126
|
+
end
|
127
|
+
alias_method_chain :type_cast_code, :hstore
|
128
|
+
alias_method_chain :simplified_type, :hstore
|
129
|
+
end
|
130
|
+
|
131
|
+
class PostgreSQLAdapter < AbstractAdapter
|
132
|
+
|
133
|
+
def native_database_types_with_hstore
|
134
|
+
native_database_types_without_hstore.merge({:hstore => { :name => "hstore" }})
|
135
|
+
end
|
136
|
+
|
137
|
+
# Quotes correctly a hstore column value.
|
138
|
+
def quote_with_hstore(value, column = nil)
|
139
|
+
if value && column && column.sql_type == 'hstore'
|
140
|
+
raise HstoreTypeMismatch, "#{column.name} must have a Hash or a valid hstore value (#{value})" unless value.kind_of?(Hash) || value.valid_hstore?
|
141
|
+
return quote_without_hstore(value.to_hstore, column)
|
142
|
+
end
|
143
|
+
quote_without_hstore(value,column)
|
144
|
+
end
|
145
|
+
|
146
|
+
alias_method_chain :quote, :hstore
|
147
|
+
alias_method_chain :native_database_types, :hstore
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Hash
|
2
|
+
HSTORE_ESCAPED = /[,\s=>\\]/
|
3
|
+
|
4
|
+
# Escapes values such that they will work in an hstore string
|
5
|
+
def hstore_escape(str)
|
6
|
+
if str.nil?
|
7
|
+
return 'NULL'
|
8
|
+
end
|
9
|
+
|
10
|
+
str = str.to_s.dup
|
11
|
+
# backslash is an escape character for strings, and an escape character for gsub, so you need 6 backslashes to get 2 in the output.
|
12
|
+
# see http://stackoverflow.com/questions/1542214/weird-backslash-substitution-in-ruby for the gory details
|
13
|
+
str.gsub!(/\\/, '\\\\\\')
|
14
|
+
# escape backslashes before injecting more backslashes
|
15
|
+
str.gsub!(/"/, '\"')
|
16
|
+
|
17
|
+
if str =~ HSTORE_ESCAPED or str.empty?
|
18
|
+
str = '"%s"' % str
|
19
|
+
end
|
20
|
+
|
21
|
+
return str
|
22
|
+
end
|
23
|
+
|
24
|
+
# Generates an hstore string format. This is the format used
|
25
|
+
# to insert or update stuff in the database.
|
26
|
+
def to_hstore
|
27
|
+
return "" if empty?
|
28
|
+
|
29
|
+
map do |idx, val|
|
30
|
+
"%s=>%s" % [hstore_escape(idx), hstore_escape(val)]
|
31
|
+
end * ","
|
32
|
+
end
|
33
|
+
|
34
|
+
# If the method from_hstore is called in a Hash, it just returns self.
|
35
|
+
def from_hstore
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# If the value os a column is already a String and it calls to_hstore, it
|
4
|
+
# just returns self. Validation occurs afterwards.
|
5
|
+
def to_hstore
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
# Validates the hstore format. Valid formats are:
|
10
|
+
# * An empty string
|
11
|
+
# * A string like %("foo"=>"bar"). I'll call it a "double quoted hstore format".
|
12
|
+
# * A string like %(foo=>bar). Postgres doesn't emit this but it does accept it as input, we should accept any input Postgres does
|
13
|
+
|
14
|
+
def valid_hstore?
|
15
|
+
pair = hstore_pair
|
16
|
+
!!match(/^\s*(#{pair}\s*(,\s*#{pair})*)?\s*$/)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Creates a hash from a valid double quoted hstore format, 'cause this is the format
|
20
|
+
# that postgresql spits out.
|
21
|
+
def from_hstore
|
22
|
+
token_pairs = (scan(hstore_pair)).map { |k,v| [k,v =~ /^NULL$/i ? nil : v] }
|
23
|
+
token_pairs = token_pairs.map { |k,v|
|
24
|
+
[k,v].map { |t|
|
25
|
+
case t
|
26
|
+
when nil then t
|
27
|
+
when /^"(.*)"$/ then $1.gsub(/\\(.)/, '\1')
|
28
|
+
else t.gsub(/\\(.)/, '\1')
|
29
|
+
end
|
30
|
+
}
|
31
|
+
}
|
32
|
+
Hash[ token_pairs ]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def hstore_pair
|
38
|
+
quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
|
39
|
+
unquoted_string = /[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
|
40
|
+
string = /(#{quoted_string}|#{unquoted_string})/
|
41
|
+
/#{string}\s*=>\s*#{string}/
|
42
|
+
end
|
43
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'activerecord-posgres-hstore-core'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
describe "Direct DB Changes for Hstore" do
|
3
|
+
before(:each) do
|
4
|
+
clean_database!
|
5
|
+
@hstore = HstoreModel.new(:name => "Bob Jones")
|
6
|
+
@normal = NormalModel.new(:name => "Jane Smith")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be an hstore sql type" do
|
10
|
+
@hstore.class.columns_hash['key_value'].sql_type.should =="hstore"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be an hstore type" do
|
14
|
+
@hstore.class.columns_hash['key_value'].type.should == :hstore
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should take a hash" do
|
18
|
+
@hstore.key_value = {"test" => 1}
|
19
|
+
@hstore.save
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not take a number" do
|
23
|
+
@hstore.key_value = 2
|
24
|
+
expect{ @hstore.save }.to raise_error(NoMethodError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not save an ilformatted string" do
|
28
|
+
@hstore.key_value = "test"
|
29
|
+
@hstore.save
|
30
|
+
@hstore.key_value.should == {}
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should take and save a hash" do
|
34
|
+
@hstore.key_value = {"test" => 1, "t2" => 2}
|
35
|
+
@hstore.save
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should overwrite correclty in db" do
|
39
|
+
@hstore.key_value = {"a" => 1, "a" => 2}
|
40
|
+
@hstore.save
|
41
|
+
db_hstore = HstoreModel.find_by_name(@hstore.name)
|
42
|
+
db_hstore.key_value.should == {"a" => "2"}
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
describe "Datatypes Changes for Hstore" do
|
3
|
+
it "should recognize a valid hstore string" do
|
4
|
+
"".valid_hstore?.should be_true
|
5
|
+
"a=>b".valid_hstore?.should be_true
|
6
|
+
'"a"=>"b"'.valid_hstore?.should be_true
|
7
|
+
'"a" => "b"'.valid_hstore?.should be_true
|
8
|
+
'"a"=>"b","c"=>"d"'.valid_hstore?.should be_true
|
9
|
+
'"a"=>"b", "c"=>"d"'.valid_hstore?.should be_true
|
10
|
+
'"a" => "b", "c"=>"d"'.valid_hstore?.should be_true
|
11
|
+
'"a"=>"b","c" => "d"'.valid_hstore?.should be_true
|
12
|
+
'k => v'.valid_hstore?.should be_true
|
13
|
+
'foo => bar, baz => whatever'.valid_hstore?.should be_true
|
14
|
+
'"1-a" => "anything at all"'.valid_hstore?.should be_true
|
15
|
+
'key => NULL'.valid_hstore?.should be_true
|
16
|
+
%q(c=>"}", "\"a\""=>"b \"a b").valid_hstore?.should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should not recognize an invalid hstore string" do
|
20
|
+
'"a"=>"b",Hello?'.valid_hstore?.should be_false
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should convert hash to hstore string and back (sort of)" do
|
24
|
+
{:a => 1, :b => 2}.to_hstore.from_hstore.should eq({"a" => "1", "b" => "2"})
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should convert hstore string to hash" do
|
28
|
+
'"a"=>"1", "b"=>"2"'.from_hstore.should eq({'a' => '1', 'b' => '2'})
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should quote correctly" do
|
32
|
+
{:a => "'a'"}.to_hstore.should eq(%q(a=>'a'))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should quote keys correctly" do
|
36
|
+
{"'a'" => "a"}.to_hstore.should eq(%q('a'=>a))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should preserve null values on store" do
|
40
|
+
# NULL=>b will be interpreted as the string pair "NULL"=>"b"
|
41
|
+
|
42
|
+
{'a' => nil,nil=>'b'}.to_hstore.should eq(%q(a=>NULL,NULL=>b))
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should preserve null values on load" do
|
46
|
+
'a=>null,b=>NuLl,c=>"NuLl",null=>c'.from_hstore.should eq({'a'=>nil,'b'=>nil,'c'=>'NuLl','null'=>'c'})
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should quote tokens with nothing space comma equals or greaterthan" do
|
50
|
+
{' '=>''}.to_hstore.should eq(%q(" "=>""))
|
51
|
+
{','=>''}.to_hstore.should eq(%q(","=>""))
|
52
|
+
{'='=>''}.to_hstore.should eq(%q("="=>""))
|
53
|
+
{'>'=>''}.to_hstore.should eq(%q(">"=>""))
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should unquote keys correctly with single quotes" do
|
57
|
+
"\"'a'\"=>\"a\"". from_hstore.should eq({"'a'" => "a"})
|
58
|
+
'\=a=>q=w'. from_hstore.should eq({"=a"=>"q=w"})
|
59
|
+
'"=a"=>q\=w'. from_hstore.should eq({"=a"=>"q=w"});
|
60
|
+
'"\"a"=>q>w'. from_hstore.should eq({"\"a"=>"q>w"});
|
61
|
+
'\"a=>q"w'. from_hstore.should eq({"\"a"=>"q\"w"})
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should quote keys and values correctly with combinations of single and double quotes" do
|
65
|
+
{ %q("a') => %q(b "a' b) }.to_hstore.should eq(%q("\"a'"=>"b \"a' b"))
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should unquote keys and values correctly with combinations of single and double quotes" do
|
69
|
+
%q("\"a'"=>"b \"a' b").from_hstore.should eq({%q("a') => %q(b "a' b)})
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should quote keys and values correctly with backslashes" do
|
73
|
+
{ %q(\\) => %q(\\) }.to_hstore.should eq(%q("\\\\"=>"\\\\"))
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should unquote keys and values correctly with backslashes" do
|
77
|
+
%q("\\\\"=>"\\\\").from_hstore.should eq({ %q(\\) => %q(\\) })
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should quote keys and values correctly with combinations of backslashes and quotes" do
|
81
|
+
{ %q(' \\ ") => %q(" \\ ') }.to_hstore.should eq(%q("' \\\\ \""=>"\" \\\\ '"))
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should unquote keys and values correctly with combinations of backslashes and quotes" do
|
85
|
+
%q("' \\\\ \""=>"\" \\\\ '").from_hstore.should eq({ %q(' \\ ") => %q(" \\ ') })
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should convert empty hash" do
|
89
|
+
{}.to_hstore.should eq("")
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should convert empty string" do
|
93
|
+
''.from_hstore.should eq({})
|
94
|
+
' '.from_hstore.should eq({})
|
95
|
+
end
|
96
|
+
end
|
data/spec/models.rb
ADDED
data/spec/schema.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define :version => 0 do
|
2
|
+
|
3
|
+
create_table :hstore_models, :force => true do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
t.column :key_value, :hstore
|
6
|
+
end
|
7
|
+
|
8
|
+
execute "create index concurrently idx_hstore_model_key_value on hstore_models using gist (key_value)"
|
9
|
+
|
10
|
+
create_table :normal_models, :force => true do |t|
|
11
|
+
t.column :name, :string
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
$LOAD_PATH << "." unless $LOAD_PATH.include?(".")
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler"
|
7
|
+
require 'active_record'
|
8
|
+
|
9
|
+
if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5")
|
10
|
+
raise RuntimeError, "Your bundler version is too old." +
|
11
|
+
"Run `gem install bundler` to upgrade."
|
12
|
+
end
|
13
|
+
|
14
|
+
# Set up load paths for all bundled gems
|
15
|
+
Bundler.setup
|
16
|
+
rescue Bundler::GemNotFound
|
17
|
+
raise RuntimeError, "Bundler couldn't find some gems." +
|
18
|
+
"Did you run \`bundlee install\`?"
|
19
|
+
end
|
20
|
+
|
21
|
+
Bundler.require
|
22
|
+
#require File.expand_path('../../lib/activerecord-postgres-hstore-core', __FILE__)
|
23
|
+
|
24
|
+
db_name = 'postgresql'
|
25
|
+
database_yml = File.expand_path('../database.yml', __FILE__)
|
26
|
+
|
27
|
+
if File.exists?(database_yml)
|
28
|
+
active_record_configuration = YAML.load_file(database_yml)
|
29
|
+
|
30
|
+
ActiveRecord::Base.configurations = active_record_configuration
|
31
|
+
config = ActiveRecord::Base.configurations[db_name]
|
32
|
+
|
33
|
+
begin
|
34
|
+
ActiveRecord::Base.establish_connection(db_name)
|
35
|
+
ActiveRecord::Base.connection
|
36
|
+
rescue
|
37
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
38
|
+
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8'))
|
39
|
+
end
|
40
|
+
|
41
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
|
42
|
+
ActiveRecord::Base.default_timezone = :utc
|
43
|
+
|
44
|
+
ActiveRecord::Base.silence do
|
45
|
+
ActiveRecord::Migration.verbose = false
|
46
|
+
|
47
|
+
load(File.dirname(__FILE__) + '/schema.rb')
|
48
|
+
load(File.dirname(__FILE__) + '/models.rb')
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample"
|
52
|
+
end
|
53
|
+
|
54
|
+
def clean_database!
|
55
|
+
models = [HstoreModel, NormalModel]
|
56
|
+
models.each do |model|
|
57
|
+
ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
clean_database!
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-postgres-hstore-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jt Gleason
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-02-29 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rails
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 7
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
- 0
|
32
|
+
version: "3.0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 15
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 6
|
47
|
+
version: "2.6"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: ammeter
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 29
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
- 1
|
62
|
+
- 3
|
63
|
+
version: 0.1.3
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: pg
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id004
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: guard
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
type: :development
|
93
|
+
version_requirements: *id005
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
96
|
+
prerelease: false
|
97
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
type: :development
|
107
|
+
version_requirements: *id006
|
108
|
+
description: Allows you to use active record with databases that already have an hstore type
|
109
|
+
email: jt@twitch.tv
|
110
|
+
executables: []
|
111
|
+
|
112
|
+
extensions: []
|
113
|
+
|
114
|
+
extra_rdoc_files: []
|
115
|
+
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- Rakefile
|
120
|
+
- activerecord-postgres-hstore-core.gemspec
|
121
|
+
- lib/activerecord-postgres-hstore-core.rb
|
122
|
+
- lib/activerecord-postgres-hstore-core/version.rb
|
123
|
+
- lib/activerecord_postgres_hstore_core/activerecord.rb
|
124
|
+
- lib/activerecord_postgres_hstore_core/hash.rb
|
125
|
+
- lib/activerecord_postgres_hstore_core/string.rb
|
126
|
+
- rails/init.rb
|
127
|
+
- spec/activerecord_postgres_hstore_core/activerecord_posgres_hstore_database_spec.rb
|
128
|
+
- spec/activerecord_postgres_hstore_core/activerecord_postgres_hstore_datatype_spec.rb
|
129
|
+
- spec/database.yml.sample
|
130
|
+
- spec/models.rb
|
131
|
+
- spec/schema.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
homepage: ""
|
134
|
+
licenses: []
|
135
|
+
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
hash: 3
|
147
|
+
segments:
|
148
|
+
- 0
|
149
|
+
version: "0"
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 3
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
version: "0"
|
159
|
+
requirements: []
|
160
|
+
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 1.8.6
|
163
|
+
signing_key:
|
164
|
+
specification_version: 3
|
165
|
+
summary: Hstore AR for Hstore DB
|
166
|
+
test_files:
|
167
|
+
- spec/activerecord_postgres_hstore_core/activerecord_posgres_hstore_database_spec.rb
|
168
|
+
- spec/activerecord_postgres_hstore_core/activerecord_postgres_hstore_datatype_spec.rb
|
169
|
+
- spec/database.yml.sample
|
170
|
+
- spec/models.rb
|
171
|
+
- spec/schema.rb
|
172
|
+
- spec/spec_helper.rb
|