From 76ac8f0c243554ae86ba5ce4e109e03955656e38 Mon Sep 17 00:00:00 2001 From: Jeremy McNevin Date: Tue, 25 Sep 2012 13:22:19 -0500 Subject: [PATCH] Adding back Jruby compatibility. --- Gemfile | 13 +- Gemfile.lock | 13 +- activerecord-postgres-hstore.gemspec | 15 +- app/Gemfile | 26 +- app/Gemfile.lock | 150 +++-- app/db/development_structure.sql | 62 +- app/db/structure.sql | 584 ++++++++++++++++++ app/test/unit/bar_test.rb | 35 +- .../activerecord.rb | 46 +- 9 files changed, 771 insertions(+), 173 deletions(-) create mode 100644 app/db/structure.sql diff --git a/Gemfile b/Gemfile index e6b658d..dbb716b 100644 --- a/Gemfile +++ b/Gemfile @@ -1,15 +1,14 @@ source "http://rubygems.org" -# Add dependencies required to use your gem here. + gem 'rails' gem 'rake' -gem 'pg' -# Add dependencies to develop your gem here. -# Include everything needed to run rake, tests, features, etc. +gem 'pg', :platform => :ruby +gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby + group :development, :test do - gem "shoulda", ">= 0" - gem "bundler", "~> 1.1.3" - gem "jeweler", "~> 1.8.3" + gem "shoulda" + gem "jeweler" gem "rdoc" gem "rspec" end diff --git a/Gemfile.lock b/Gemfile.lock index 14eef1b..403068c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -22,6 +22,10 @@ GEM activesupport (= 3.2.8) arel (~> 3.0.2) tzinfo (~> 0.3.29) + activerecord-jdbc-adapter (1.2.2) + activerecord-jdbcpostgresql-adapter (1.2.2) + activerecord-jdbc-adapter (~> 1.2.2) + jdbc-postgres (>= 9.0, < 9.2) activeresource (3.2.8) activemodel (= 3.2.8) activesupport (= 3.2.8) @@ -35,6 +39,7 @@ GEM git (1.2.5) hike (1.2.1) i18n (0.6.1) + jdbc-postgres (9.1.901) jeweler (1.8.4) bundler (~> 1.0) git (>= 1.2.5) @@ -42,6 +47,7 @@ GEM rdoc journey (1.0.4) json (1.7.5) + json (1.7.5-java) mail (2.4.4) i18n (>= 0.4.0) mime-types (~> 1.16) @@ -82,7 +88,7 @@ GEM rspec-core (2.11.1) rspec-expectations (2.11.3) diff-lcs (~> 1.1.3) - rspec-mocks (2.11.2) + rspec-mocks (2.11.3) shoulda (3.1.1) shoulda-context (~> 1.0) shoulda-matchers (~> 1.2) @@ -101,11 +107,12 @@ GEM tzinfo (0.3.33) PLATFORMS + java ruby DEPENDENCIES - bundler (~> 1.1.3) - jeweler (~> 1.8.3) + activerecord-jdbcpostgresql-adapter + jeweler pg rails rake diff --git a/activerecord-postgres-hstore.gemspec b/activerecord-postgres-hstore.gemspec index 793299f..ef4e6d9 100644 --- a/activerecord-postgres-hstore.gemspec +++ b/activerecord-postgres-hstore.gemspec @@ -104,29 +104,26 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 0"]) s.add_runtime_dependency(%q, [">= 0"]) - s.add_runtime_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, ["~> 1.1.3"]) - s.add_development_dependency(%q, ["~> 1.8.3"]) + s.add_development_dependency(%q, ["~> 0"]) + s.add_development_dependency(%q, ["~> 0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 1.1.3"]) - s.add_dependency(%q, ["~> 1.8.3"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 1.1.3"]) - s.add_dependency(%q, ["~> 1.8.3"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end diff --git a/app/Gemfile b/app/Gemfile index 494454e..681bfa5 100644 --- a/app/Gemfile +++ b/app/Gemfile @@ -1,27 +1,9 @@ source 'http://rubygems.org' -gem 'rails', '3.0.0' -gem 'pg' -gem 'activerecord-postgres-hstore', :path => '../' - -# Use unicorn as the web server -# gem 'unicorn' +gem 'rails' -# Deploy with Capistrano -# gem 'capistrano' +gem 'pg', :platform => :ruby +gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby -# To use debugger -# gem 'ruby-debug' - -# Bundle the extra gems: -# gem 'bj' -# gem 'nokogiri', '1.4.1' -# gem 'sqlite3-ruby', :require => 'sqlite3' -# gem 'aws-s3', :require => 'aws/s3' +gem 'activerecord-postgres-hstore', :path => '../' -# Bundle gems for the local environment. Make sure to -# put test-only gems in this group so their generators -# and rake tasks are available in development mode: -# group :development, :test do -# gem 'webrat' -# end diff --git a/app/Gemfile.lock b/app/Gemfile.lock index 33db5c8..859fb3a 100644 --- a/app/Gemfile.lock +++ b/app/Gemfile.lock @@ -1,81 +1,103 @@ PATH remote: ../ specs: - activerecord-postgres-hstore (0.1.2) - activerecord + activerecord-postgres-hstore (0.4.1) + rails rake GEM remote: http://rubygems.org/ specs: - abstract (1.0.0) - actionmailer (3.0.0) - actionpack (= 3.0.0) - mail (~> 2.2.5) - actionpack (3.0.0) - activemodel (= 3.0.0) - activesupport (= 3.0.0) - builder (~> 2.1.2) - erubis (~> 2.6.6) - i18n (~> 0.4.1) - rack (~> 1.2.1) - rack-mount (~> 0.6.12) - rack-test (~> 0.5.4) - tzinfo (~> 0.3.23) - activemodel (3.0.0) - activesupport (= 3.0.0) - builder (~> 2.1.2) - i18n (~> 0.4.1) - activerecord (3.0.0) - activemodel (= 3.0.0) - activesupport (= 3.0.0) - arel (~> 1.0.0) - tzinfo (~> 0.3.23) - activeresource (3.0.0) - activemodel (= 3.0.0) - activesupport (= 3.0.0) - activesupport (3.0.0) - arel (1.0.1) - activesupport (~> 3.0.0) - builder (2.1.2) - erubis (2.6.6) - abstract (>= 1.0.0) - i18n (0.4.1) - mail (2.2.5) - activesupport (>= 2.3.6) - mime-types - treetop (>= 1.4.5) - mime-types (1.16) - pg (0.9.0) - polyglot (0.3.1) - rack (1.2.1) - rack-mount (0.6.13) - rack (>= 1.0.0) - rack-test (0.5.4) + actionmailer (3.2.8) + actionpack (= 3.2.8) + mail (~> 2.4.4) + actionpack (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.4) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.3) + activemodel (3.2.8) + activesupport (= 3.2.8) + builder (~> 3.0.0) + activerecord (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activerecord-jdbc-adapter (1.2.2) + activerecord-jdbcpostgresql-adapter (1.2.2) + activerecord-jdbc-adapter (~> 1.2.2) + jdbc-postgres (>= 9.0, < 9.2) + activeresource (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) + activesupport (3.2.8) + i18n (~> 0.6) + multi_json (~> 1.0) + arel (3.0.2) + builder (3.0.3) + erubis (2.7.0) + hike (1.2.1) + i18n (0.6.1) + jdbc-postgres (9.1.901) + journey (1.0.4) + json (1.7.5) + json (1.7.5-java) + mail (2.4.4) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.19) + multi_json (1.3.6) + pg (0.14.1) + polyglot (0.3.3) + rack (1.4.1) + rack-cache (1.2) + rack (>= 0.4) + rack-ssl (1.3.2) + rack + rack-test (0.6.1) rack (>= 1.0) - rails (3.0.0) - actionmailer (= 3.0.0) - actionpack (= 3.0.0) - activerecord (= 3.0.0) - activeresource (= 3.0.0) - activesupport (= 3.0.0) - bundler (~> 1.0.0) - railties (= 3.0.0) - railties (3.0.0) - actionpack (= 3.0.0) - activesupport (= 3.0.0) - rake (>= 0.8.4) - thor (~> 0.14.0) - rake (0.8.7) - thor (0.14.0) - treetop (1.4.8) + rails (3.2.8) + actionmailer (= 3.2.8) + actionpack (= 3.2.8) + activerecord (= 3.2.8) + activeresource (= 3.2.8) + activesupport (= 3.2.8) + bundler (~> 1.0) + railties (= 3.2.8) + railties (3.2.8) + actionpack (= 3.2.8) + activesupport (= 3.2.8) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (>= 0.14.6, < 2.0) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + sprockets (2.1.3) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + thor (0.16.0) + tilt (1.3.3) + treetop (1.4.10) + polyglot polyglot (>= 0.3.1) - tzinfo (0.3.23) + tzinfo (0.3.33) PLATFORMS + java ruby DEPENDENCIES + activerecord-jdbcpostgresql-adapter activerecord-postgres-hstore! pg - rails (= 3.0.0) + rails diff --git a/app/db/development_structure.sql b/app/db/development_structure.sql index e50e438..295bb52 100644 --- a/app/db/development_structure.sql +++ b/app/db/development_structure.sql @@ -4,10 +4,23 @@ SET statement_timeout = 0; SET client_encoding = 'UTF8'; -SET standard_conforming_strings = off; +SET standard_conforming_strings = on; SET check_function_bodies = false; SET client_min_messages = warning; -SET escape_string_warning = off; + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + SET search_path = public, pg_catalog; @@ -267,15 +280,6 @@ CREATE FUNCTION hs_contains(hstore, hstore) RETURNS boolean AS '$libdir/hstore', 'hs_contains'; --- --- Name: hstore(text, text); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION hstore(text, text) RETURNS hstore - LANGUAGE c IMMUTABLE - AS '$libdir/hstore', 'tconvert'; - - -- -- Name: isdefined(hstore, text); Type: FUNCTION; Schema: public; Owner: - -- @@ -432,10 +436,10 @@ CREATE OPERATOR CLASS gin_hstore_ops STORAGE text , OPERATOR 7 @>(hstore,hstore) , OPERATOR 9 ?(hstore,text) , - FUNCTION 1 bttextcmp(text,text) , - FUNCTION 2 gin_extract_hstore(internal,internal) , - FUNCTION 3 gin_extract_hstore_query(internal,internal,smallint,internal,internal) , - FUNCTION 4 gin_consistent_hstore(internal,smallint,internal,integer,internal,internal); + FUNCTION 1 (hstore, hstore) bttextcmp(text,text) , + FUNCTION 2 (hstore, hstore) gin_extract_hstore(internal,internal) , + FUNCTION 3 (hstore, hstore) gin_extract_hstore_query(internal,internal,smallint,internal,internal) , + FUNCTION 4 (hstore, hstore) gin_consistent_hstore(internal,smallint,internal,integer,internal,internal); -- @@ -448,13 +452,13 @@ CREATE OPERATOR CLASS gist_hstore_ops OPERATOR 7 @>(hstore,hstore) , OPERATOR 9 ?(hstore,text) , OPERATOR 13 @(hstore,hstore) , - FUNCTION 1 ghstore_consistent(internal,internal,integer,oid,internal) , - FUNCTION 2 ghstore_union(internal,internal) , - FUNCTION 3 ghstore_compress(internal) , - FUNCTION 4 ghstore_decompress(internal) , - FUNCTION 5 ghstore_penalty(internal,internal,internal) , - FUNCTION 6 ghstore_picksplit(internal,internal) , - FUNCTION 7 ghstore_same(internal,internal,internal); + FUNCTION 1 (hstore, hstore) ghstore_consistent(internal,internal,integer,oid,internal) , + FUNCTION 2 (hstore, hstore) ghstore_union(internal,internal) , + FUNCTION 3 (hstore, hstore) ghstore_compress(internal) , + FUNCTION 4 (hstore, hstore) ghstore_decompress(internal) , + FUNCTION 5 (hstore, hstore) ghstore_penalty(internal,internal,internal) , + FUNCTION 6 (hstore, hstore) ghstore_picksplit(internal,internal) , + FUNCTION 7 (hstore, hstore) ghstore_same(internal,internal,internal); SET default_tablespace = ''; @@ -480,8 +484,8 @@ CREATE TABLE bars ( CREATE SEQUENCE bars_id_seq START WITH 1 INCREMENT BY 1 - NO MAXVALUE NO MINVALUE + NO MAXVALUE CACHE 1; @@ -511,8 +515,8 @@ CREATE TABLE foos ( CREATE SEQUENCE foos_id_seq START WITH 1 INCREMENT BY 1 - NO MAXVALUE NO MINVALUE + NO MAXVALUE CACHE 1; @@ -536,14 +540,14 @@ CREATE TABLE schema_migrations ( -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE bars ALTER COLUMN id SET DEFAULT nextval('bars_id_seq'::regclass); +ALTER TABLE ONLY bars ALTER COLUMN id SET DEFAULT nextval('bars_id_seq'::regclass); -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE foos ALTER COLUMN id SET DEFAULT nextval('foos_id_seq'::regclass); +ALTER TABLE ONLY foos ALTER COLUMN id SET DEFAULT nextval('foos_id_seq'::regclass); -- @@ -573,8 +577,8 @@ CREATE UNIQUE INDEX unique_schema_migrations ON schema_migrations USING btree (v -- PostgreSQL database dump complete -- -INSERT INTO schema_migrations (version) VALUES ('20100906191457'); +INSERT INTO schema_migrations (version) VALUES ('20100906191151'); -INSERT INTO schema_migrations (version) VALUES ('20100906191506'); +INSERT INTO schema_migrations (version) VALUES ('20100906191457'); -INSERT INTO schema_migrations (version) VALUES ('20100906191151'); \ No newline at end of file +INSERT INTO schema_migrations (version) VALUES ('20100906191506'); \ No newline at end of file diff --git a/app/db/structure.sql b/app/db/structure.sql new file mode 100644 index 0000000..295bb52 --- /dev/null +++ b/app/db/structure.sql @@ -0,0 +1,584 @@ +-- +-- PostgreSQL database dump +-- + +SET statement_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SET check_function_bodies = false; +SET client_min_messages = warning; + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + + +SET search_path = public, pg_catalog; + +-- +-- Name: ghstore; Type: SHELL TYPE; Schema: public; Owner: - +-- + +CREATE TYPE ghstore; + + +-- +-- Name: ghstore_in(cstring); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_in(cstring) RETURNS ghstore + LANGUAGE c STRICT + AS '$libdir/hstore', 'ghstore_in'; + + +-- +-- Name: ghstore_out(ghstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_out(ghstore) RETURNS cstring + LANGUAGE c STRICT + AS '$libdir/hstore', 'ghstore_out'; + + +-- +-- Name: ghstore; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE ghstore ( + INTERNALLENGTH = variable, + INPUT = ghstore_in, + OUTPUT = ghstore_out, + ALIGNMENT = int4, + STORAGE = plain +); + + +-- +-- Name: hstore; Type: SHELL TYPE; Schema: public; Owner: - +-- + +CREATE TYPE hstore; + + +-- +-- Name: hstore_in(cstring); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION hstore_in(cstring) RETURNS hstore + LANGUAGE c STRICT + AS '$libdir/hstore', 'hstore_in'; + + +-- +-- Name: hstore_out(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION hstore_out(hstore) RETURNS cstring + LANGUAGE c STRICT + AS '$libdir/hstore', 'hstore_out'; + + +-- +-- Name: hstore; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE hstore ( + INTERNALLENGTH = variable, + INPUT = hstore_in, + OUTPUT = hstore_out, + ALIGNMENT = int4, + STORAGE = extended +); + + +-- +-- Name: akeys(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION akeys(hstore) RETURNS text[] + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'akeys'; + + +-- +-- Name: avals(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION avals(hstore) RETURNS text[] + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'avals'; + + +-- +-- Name: defined(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION defined(hstore, text) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'defined'; + + +-- +-- Name: delete(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION delete(hstore, text) RETURNS hstore + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'delete'; + + +-- +-- Name: each(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION each(hs hstore, OUT key text, OUT value text) RETURNS SETOF record + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'each'; + + +-- +-- Name: exist(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION exist(hstore, text) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'exists'; + + +-- +-- Name: fetchval(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION fetchval(hstore, text) RETURNS text + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'fetchval'; + + +-- +-- Name: ghstore_compress(internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_compress(internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_compress'; + + +-- +-- Name: ghstore_consistent(internal, internal, integer, oid, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_consistent(internal, internal, integer, oid, internal) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_consistent'; + + +-- +-- Name: ghstore_decompress(internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_decompress(internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_decompress'; + + +-- +-- Name: ghstore_penalty(internal, internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_penalty(internal, internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_penalty'; + + +-- +-- Name: ghstore_picksplit(internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_picksplit(internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_picksplit'; + + +-- +-- Name: ghstore_same(internal, internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_same(internal, internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_same'; + + +-- +-- Name: ghstore_union(internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION ghstore_union(internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'ghstore_union'; + + +-- +-- Name: gin_consistent_hstore(internal, smallint, internal, integer, internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION gin_consistent_hstore(internal, smallint, internal, integer, internal, internal) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'gin_consistent_hstore'; + + +-- +-- Name: gin_extract_hstore(internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION gin_extract_hstore(internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'gin_extract_hstore'; + + +-- +-- Name: gin_extract_hstore_query(internal, internal, smallint, internal, internal); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION gin_extract_hstore_query(internal, internal, smallint, internal, internal) RETURNS internal + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'gin_extract_hstore_query'; + + +-- +-- Name: hs_concat(hstore, hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION hs_concat(hstore, hstore) RETURNS hstore + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'hs_concat'; + + +-- +-- Name: hs_contained(hstore, hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION hs_contained(hstore, hstore) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'hs_contained'; + + +-- +-- Name: hs_contains(hstore, hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION hs_contains(hstore, hstore) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'hs_contains'; + + +-- +-- Name: isdefined(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION isdefined(hstore, text) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'defined'; + + +-- +-- Name: isexists(hstore, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION isexists(hstore, text) RETURNS boolean + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'exists'; + + +-- +-- Name: skeys(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION skeys(hstore) RETURNS SETOF text + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'skeys'; + + +-- +-- Name: svals(hstore); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION svals(hstore) RETURNS SETOF text + LANGUAGE c IMMUTABLE STRICT + AS '$libdir/hstore', 'svals'; + + +-- +-- Name: tconvert(text, text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION tconvert(text, text) RETURNS hstore + LANGUAGE c IMMUTABLE + AS '$libdir/hstore', 'tconvert'; + + +-- +-- Name: ->; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR -> ( + PROCEDURE = fetchval, + LEFTARG = hstore, + RIGHTARG = text +); + + +-- +-- Name: <@; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR <@ ( + PROCEDURE = hs_contained, + LEFTARG = hstore, + RIGHTARG = hstore, + COMMUTATOR = @>, + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- +-- Name: =>; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR => ( + PROCEDURE = tconvert, + LEFTARG = text, + RIGHTARG = text +); + + +-- +-- Name: ?; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR ? ( + PROCEDURE = exist, + LEFTARG = hstore, + RIGHTARG = text, + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- +-- Name: @; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR @ ( + PROCEDURE = hs_contains, + LEFTARG = hstore, + RIGHTARG = hstore, + COMMUTATOR = ~, + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- +-- Name: @>; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR @> ( + PROCEDURE = hs_contains, + LEFTARG = hstore, + RIGHTARG = hstore, + COMMUTATOR = <@, + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- +-- Name: ||; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR || ( + PROCEDURE = hs_concat, + LEFTARG = hstore, + RIGHTARG = hstore +); + + +-- +-- Name: ~; Type: OPERATOR; Schema: public; Owner: - +-- + +CREATE OPERATOR ~ ( + PROCEDURE = hs_contained, + LEFTARG = hstore, + RIGHTARG = hstore, + COMMUTATOR = @, + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- +-- Name: gin_hstore_ops; Type: OPERATOR CLASS; Schema: public; Owner: - +-- + +CREATE OPERATOR CLASS gin_hstore_ops + DEFAULT FOR TYPE hstore USING gin AS + STORAGE text , + OPERATOR 7 @>(hstore,hstore) , + OPERATOR 9 ?(hstore,text) , + FUNCTION 1 (hstore, hstore) bttextcmp(text,text) , + FUNCTION 2 (hstore, hstore) gin_extract_hstore(internal,internal) , + FUNCTION 3 (hstore, hstore) gin_extract_hstore_query(internal,internal,smallint,internal,internal) , + FUNCTION 4 (hstore, hstore) gin_consistent_hstore(internal,smallint,internal,integer,internal,internal); + + +-- +-- Name: gist_hstore_ops; Type: OPERATOR CLASS; Schema: public; Owner: - +-- + +CREATE OPERATOR CLASS gist_hstore_ops + DEFAULT FOR TYPE hstore USING gist AS + STORAGE ghstore , + OPERATOR 7 @>(hstore,hstore) , + OPERATOR 9 ?(hstore,text) , + OPERATOR 13 @(hstore,hstore) , + FUNCTION 1 (hstore, hstore) ghstore_consistent(internal,internal,integer,oid,internal) , + FUNCTION 2 (hstore, hstore) ghstore_union(internal,internal) , + FUNCTION 3 (hstore, hstore) ghstore_compress(internal) , + FUNCTION 4 (hstore, hstore) ghstore_decompress(internal) , + FUNCTION 5 (hstore, hstore) ghstore_penalty(internal,internal,internal) , + FUNCTION 6 (hstore, hstore) ghstore_picksplit(internal,internal) , + FUNCTION 7 (hstore, hstore) ghstore_same(internal,internal,internal); + + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: bars; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE bars ( + id integer NOT NULL, + data hstore, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: bars_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE bars_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: bars_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE bars_id_seq OWNED BY bars.id; + + +-- +-- Name: foos; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE foos ( + id integer NOT NULL, + data text, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: foos_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE foos_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: foos_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE foos_id_seq OWNED BY foos.id; + + +-- +-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE schema_migrations ( + version character varying(255) NOT NULL +); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY bars ALTER COLUMN id SET DEFAULT nextval('bars_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY foos ALTER COLUMN id SET DEFAULT nextval('foos_id_seq'::regclass); + + +-- +-- Name: bars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY bars + ADD CONSTRAINT bars_pkey PRIMARY KEY (id); + + +-- +-- Name: foos_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY foos + ADD CONSTRAINT foos_pkey PRIMARY KEY (id); + + +-- +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX unique_schema_migrations ON schema_migrations USING btree (version); + + +-- +-- PostgreSQL database dump complete +-- + +INSERT INTO schema_migrations (version) VALUES ('20100906191151'); + +INSERT INTO schema_migrations (version) VALUES ('20100906191457'); + +INSERT INTO schema_migrations (version) VALUES ('20100906191506'); \ No newline at end of file diff --git a/app/test/unit/bar_test.rb b/app/test/unit/bar_test.rb index 9fc54e7..7c35fbb 100644 --- a/app/test/unit/bar_test.rb +++ b/app/test/unit/bar_test.rb @@ -4,23 +4,24 @@ class BarTest < ActiveSupport::TestCase test "should create contact" do - assert Bar.create :data => {:a => 1, :b => 2} + assert Bar.create! :data => {:a => 1, :b => 2} end test "should raise HstoreTypeMismatch" do assert_raises ActiveRecord::HstoreTypeMismatch do - assert Bar.create :data => "bug" + assert Bar.create! :data => "bug" end end test "should read values from contact" do - bar = Bar.create :data => {:a => 1, :b => "Lorem ipsum", 'other stuff' => "'''a'''"} - assert_equal({'a' => '1', 'b' => 'Lorem ipsum', 'other stuff' => "'''a'''"}, Bar.find(bar.id).data) + bar = Bar.create! :data => {:a => 1, :b => "Lorem ipsum", 'other stuff' => "'''a'''"} + assert_equal({'a' => '1', 'b' => 'Lorem ipsum', 'other stuff' => "'''a'''"}, + Bar.find(bar.id).data) end test "should search" do Array.new(10){|i| - Bar.create :data => {:a => "value#{i}"} + Bar.create! :data => {:a => "value#{i}"} } assert_equal 10, Bar.where("data ? 'a'").count assert_equal 1, Bar.where("data -> 'a' = 'value5'").count @@ -33,7 +34,7 @@ class BarTest < ActiveSupport::TestCase end test "should delete with workaround" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) data = bar.data @@ -43,9 +44,9 @@ class BarTest < ActiveSupport::TestCase bar.reload assert_equal({"b"=>"2", "c"=>"3"}, bar.data) end - + test "should delete in a cool way" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) bar.destroy_key(:data, :a) @@ -55,16 +56,16 @@ class BarTest < ActiveSupport::TestCase end test "should delete in a cool way - bang version" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) assert bar.destroy_key!(:data, :a) bar.reload assert_equal({"b"=>"2", "c"=>"3"}, bar.data) end - + test "should delete many keys" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) bar.destroy_keys(:data, :a, :b) @@ -74,16 +75,16 @@ class BarTest < ActiveSupport::TestCase end test "should delete many keys - bang version" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) assert bar.destroy_keys!(:data, :a, :b) bar.reload assert_equal({"c"=>"3"}, bar.data) end - + test "should delete using method chaining" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} bar.reload assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) bar.destroy_key(:data, :a).destroy_key(:data, :b).destroy_key(:data, :c).save @@ -92,7 +93,7 @@ class BarTest < ActiveSupport::TestCase end test "should delete from the model" do - bars = Array.new(5){ Bar.create :data => {:a => 1, :b => 2, :c => 3} } + bars = Array.new(5){ Bar.create! :data => {:a => 1, :b => 2, :c => 3} } bars.map(&:reload) for bar in bars assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) @@ -105,7 +106,7 @@ class BarTest < ActiveSupport::TestCase end test "should delete many keys from the model" do - bars = Array.new(5){ Bar.create :data => {:a => 1, :b => 2, :c => 3} } + bars = Array.new(5){ Bar.create! :data => {:a => 1, :b => 2, :c => 3} } bars.map(&:reload) for bar in bars assert_equal({"a"=>"1", "b"=>"2", "c"=>"3"}, bar.data) @@ -118,7 +119,7 @@ class BarTest < ActiveSupport::TestCase end test "should explode if there is not column trying to delete from the record" do - bar = Bar.create :data => {:a => 1, :b => 2, :c => 3} + bar = Bar.create! :data => {:a => 1, :b => 2, :c => 3} assert_raise RuntimeError do bar.destroy_key(:foo, :a) end diff --git a/lib/activerecord-postgres-hstore/activerecord.rb b/lib/activerecord-postgres-hstore/activerecord.rb index 0ed21fd..68220bf 100644 --- a/lib/activerecord-postgres-hstore/activerecord.rb +++ b/lib/activerecord-postgres-hstore/activerecord.rb @@ -67,30 +67,29 @@ def destroy_keys! attribute, *keys end if defined?(Rails) && Rails.version < '3.1.0' - # This method is replaced for Rails 3 compatibility. - # All I do is add the condition when the field is a hash that converts the value - # to hstore format. - # IMHO this should be delegated to the column, so it won't be necessary to rewrite all - # this method. - def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys) - attrs = {} - attribute_names.each do |name| - if (column = column_for_attribute(name)) && (include_primary_key || !column.primary) - if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name)) - value = read_attribute(name) - if self.class.columns_hash[name].type == :hstore && value && value.is_a?(Hash) - value = value.to_hstore # Done! - 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)) - value = value.to_yaml + # This method is replaced for Rails 3 compatibility. + # All I do is add the condition when the field is a hash that converts the value + # to hstore format. + # IMHO this should be delegated to the column, so it won't be necessary to rewrite all + # this method. + def arel_attributes_values(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys) + attrs = {} + attribute_names.each do |name| + if (column = column_for_attribute(name)) && (include_primary_key || !column.primary) + if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name)) + value = read_attribute(name) + if self.class.columns_hash[name].type == :hstore && value && value.is_a?(Hash) + value = value.to_hstore # Done! + 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)) + value = value.to_yaml + end + attrs[self.class.arel_table[name]] = value end - attrs[self.class.arel_table[name]] = value end end + attrs end - attrs end - end - end # This erro class is used when the user passes a wrong value to a hstore column. @@ -133,7 +132,7 @@ def hstore(*args) end - class PostgreSQLColumn < Column + PostgreSQLColumn.class_eval do # Does the type casting from hstore columns using String#from_hstore or Hash#from_hstore. def type_cast_code_with_hstore(var_name) type == :hstore ? "#{var_name}.from_hstore" : type_cast_code_without_hstore(var_name) @@ -148,7 +147,7 @@ def simplified_type_with_hstore(field_type) alias_method_chain :simplified_type, :hstore end - class PostgreSQLAdapter < AbstractAdapter + PostgreSQLAdapter.class_eval do def native_database_types_with_hstore native_database_types_without_hstore.merge({:hstore => { :name => "hstore" }}) end @@ -156,7 +155,10 @@ def native_database_types_with_hstore # Quotes correctly a hstore column value. def quote_with_hstore(value, column = nil) if value && column && column.sql_type == 'hstore' - raise HstoreTypeMismatch, "#{column.name} must have a Hash or a valid hstore value (#{value})" unless value.kind_of?(Hash) || value.valid_hstore? + if !value.kind_of?(Hash) && !value.valid_hstore? + raise HstoreTypeMismatch, + "#{column.name} must have a Hash or a valid hstore value (#{value})" + end return quote_without_hstore(value.to_hstore, column) end quote_without_hstore(value,column)