GithubHelp home page GithubHelp logo

activerecord-postgres-hstore's Introduction

DEPRECATED - Just use Rails JSON or HStore built-in support.

If you are using Rails 4 you don't need this gem as ActiveRecord 4 provides HStore type support out of the box. ActiveRecord will see your HStore column and do all of the work for you. Additional code is no longer needed.

You can test it with a migration like this:

class CreateTest < ActiveRecord::Migration
  def change
    create_table :tests do |t|
      t.hstore :data
    end
  end
end

Its model:

class Test < ActiveRecord::Base
  # before Rails 4, we'd have to this here:
  # serialize :data, ActiveRecord::Coders::Hstore
end

Then you can use the hash field straight away:

irb(main):003:0> t = Test.new data: {a: 1, b:2}
=> #<Test id: nil, data: {"a"=>"1", "b"=>"2"}>
irb(main):004:0> t.save!
   (0.3ms)  BEGIN
  SQL (2.3ms)  INSERT INTO "tests" ("data") VALUES ($1) RETURNING "id"  [["data", "\"a\"=>\"1\",\"b\"=>\"2\""]]
   (0.5ms)  COMMIT
=> true
irb(main):005:0> t
=> #<Test id: 1, data: {"a"=>"1", "b"=>"2"}>
irb(main):006:0> t.data
=> {"a"=>"1", "b"=>"2"}
irb(main):007:0> t.data['a']
=> "1"

For more information take a look here

Common use cases

Add settings to users, like in rails-settings or HasEasy.

class User < ActiveRecord::Base
  serialize :settings, ActiveRecord::Coders::Hstore
end
user = User.create settings: {theme: 'navy'}
user.settings['theme']

Requirements

Postgresql 8.4+ with contrib and Rails 3.1+ (If you want to try on older rails versions I recommend the 0.6 and ealier versions of this gem) On Ubuntu, this is easy: sudo apt-get install postgresql-contrib-9.1

On Mac you have a couple of options:

Install

Hstore is a PostgreSQL contrib type, check it out first.

Then, just add this to your Gemfile:

gem 'activerecord-postgres-hstore'

And run your bundler:

bundle install

Now you need to create a migration that adds hstore support for your PostgreSQL database:

rails g hstore:setup

Run it:

rake db:migrate

Finally you can create your own tables using hstore type. It’s easy:

rails g model Person name:string data:hstore
rake db:migrate

You’re done. Well, not yet. Don’t forget to add indexes. Like this:

CREATE INDEX people_gist_data ON people USING GIST(data);

or

CREATE INDEX people_gin_data ON people USING GIN(data);

This gem provides some functions to generate this kind of index inside your migrations. For the model Person we could create an index (defaults to type GIST) over the data field with this migration:

class AddIndexToPeople < ActiveRecord::Migration
  def change
    add_hstore_index :people, :data
  end
end

To understand the difference between the two types of indexes take a look at PostgreSQL docs.

Usage

This gem only provides a custom serialization coder. If you want to use it just put in your Gemfile:

gem 'activerecord-postgres-hstore'

Now add a line (for each hstore column) on the model you have your hstore columns. Assuming a model called Person, with a data field on it, the code should look like:

class Person < ActiveRecord::Base
  serialize :data, ActiveRecord::Coders::Hstore
end

This way, you will automatically start with an empty hash that you can write attributes to.

irb(main):001:0> person = Person.new
=> #<Person id: nil, name: nil, data: {}, created_at: nil, updated_at: nil>
irb(main):002:0> person.data['favorite_color'] = 'blue'
=> "blue"

Querying the database

Now you just need to learn a little bit of new sqls for selecting stuff (creating and updating is transparent). Find records that contains a key named 'foo’:

Person.where("data ? 'foo'")

Find records where 'foo’ is equal to 'bar’:

Person.where("data -> 'foo' = 'bar'")

This same sql is at least twice as fast (using indexes) if you do it that way:

Person.where("data @> 'foo=>bar'")

Find records where 'foo’ is not equal to 'bar’:

Person.where("data -> 'foo' <> 'bar'")

Find records where 'foo’ is like 'bar’:

Person.where("data -> 'foo' LIKE '%bar%'")

If you need to delete a key in a record, you can do it that way:

person.destroy_key(:data, :foo)

This way you’ll also save the record:

person.destroy_key!(:data, :foo)

The destroy_key method returns 'self’, so you can chain it:

person.destroy_key(:data, :foo).destroy_key(:data, :bar).save

But there is a shortcuts for that:

person.destroy_keys(:data, :foo, :bar)

And finally, if you need to delete keys in many rows, you can:

Person.delete_key(:data, :foo)

and with many keys:

Person.delete_keys(:data, :foo, :bar)

Caveats

hstore keys and values have to be strings. This means true will become "true" and 42 will become "42" after you save the record. Only nil values are preserved.

It is also confusing when querying:

Person.where("data -> 'foo' = :value", value: true).to_sql
#=> SELECT "people".* FROM "people" WHERE ("data -> 'foo' = 't'") # notice 't'

To avoid the above, make sure all named parameters are strings:

Person.where("data -> 'foo' = :value", value: some_var.to_s)

Have fun.

Test Database

To have hstore enabled when you load your database schema (as happens in rake db:test:prepare), you have two options.

The first option is creating a template database with hstore installed and set the template option in database.yml to that database. If you use the template1 database for this you don't even need to set the template option, but the extension will be installed in all your databases from now on by default. To install the extension in your template1 database you could simply run:

psql -d template1 -c 'create extension hstore;'

The second option is to uncomment or add the following line in config/application.rb

config.active_record.schema_format = :sql

This will change your schema dumps from Ruby to SQL. If you're unsure about the implications of this change, we suggest reading this Rails Guide.

Help

You can use issues in github for that. Or else you can reach us at twitter: @dbiazus or @joaomilho

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don’t break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (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)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright © 2010 Juan Maiz. See LICENSE for details.

activerecord-postgres-hstore's People

Contributors

betelgeuse avatar bryant1410 avatar cqr avatar darrencauthon avatar diogob avatar dotemacs avatar dpayonk avatar ecin avatar eshear avatar espen avatar greysteil avatar joaomilho avatar kevmoo avatar kgilpin avatar kiela avatar matrushka avatar msheakoski avatar nicolasleger avatar releu avatar ren avatar seamusabshere avatar tadast avatar teeparham avatar tomtaylor avatar virtualstaticvoid avatar willglynn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

activerecord-postgres-hstore's Issues

Serializing arrays

I have a need to serialize an array of values as a way to store and represent multiple selections from a drop down list. I have written some code (https://gist.github.com/3189117) that converts the Array to a hash of keys with values set to true so that they can be stored and easily queried as hstore.

I am wondering if this might be something desirable to be included in some way as part of the gem. I can easily convert the attribute writer method to an Array#to_hstore but there would need to be some solution for detecting the array in order to convert it back to an Array.

I am new to hstore so I might be missing something obvious about all this so I thought I would just put this out there to get some ideas and feedback.

Support double quotes

The hstore coder does not support double quoted values. Double-quoted values get split into more key/value pairs & the insert generally fails.

I added a few specs to test the coder. I'm not sure what the solution is, but it seems like the coder should double escape double quotes in values.

This fails:

    context 'when value has double quotes' do
      let(:value){ {"a" => "\"a\""} }
      it{ should eql(%q("a"=>""a"")) }
    end

If you double-escape the double quotes, it works:

    context 'when value has double quotes' do
      let(:value){ {"a" => "\\\"a\\\""} }
      it{ should eql(%q("a"=>"\"a\"")) }
    end

I added the specs here:
teeparham@d1fbf7ee1b40e302c9

Can't find :hstore type when prepping DB for test

Works fine from the dev console. However, prepping the DB for testing with rspec, running:

`rake db:test:prepare``

I get this:

$ rake db:test:prepare --trace
** Invoke db:test:prepare (first_time)
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:abort_if_pending_migrations
** Execute db:test:prepare
** Invoke db:test:load (first_time)
** Invoke db:test:purge (first_time)
** Invoke environment
** Execute db:test:purge
** Execute db:test:load
** Invoke db:test:load_schema (first_time)
** Invoke db:test:purge
** Execute db:test:load_schema
** Invoke db:schema:load (first_time)
** Invoke environment
** Execute db:schema:load
NOTICE: CREATE TABLE will create implicit sequence "analytic_logs_id_seq" for serial column "analytic_logs.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "analytic_logs_pkey" for table "analytic_logs"
NOTICE: CREATE TABLE will create implicit sequence "educations_id_seq" for serial column "educations.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "educations_pkey" for table "educations"
NOTICE: CREATE TABLE will create implicit sequence "employers_id_seq" for serial column "employers.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "employers_pkey" for table "employers"
NOTICE: CREATE TABLE will create implicit sequence "industries_id_seq" for serial column "industries.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "industries_pkey" for table "industries"
NOTICE: CREATE TABLE will create implicit sequence "interests_id_seq" for serial column "interests.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "interests_pkey" for table "interests"
NOTICE: CREATE TABLE will create implicit sequence "jobs_id_seq" for serial column "jobs.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "jobs_pkey" for table "jobs"
NOTICE: CREATE TABLE will create implicit sequence "messages_id_seq" for serial column "messages.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "messages_pkey" for table "messages"
NOTICE: CREATE TABLE will create implicit sequence "needs_id_seq" for serial column "needs.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "needs_pkey" for table "needs"
NOTICE: CREATE TABLE will create implicit sequence "schools_id_seq" for serial column "schools.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "schools_pkey" for table "schools"
NOTICE: CREATE TABLE will create implicit sequence "skills_id_seq" for serial column "skills.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "skills_pkey" for table "skills"
NOTICE: CREATE TABLE will create implicit sequence "users_id_seq" for serial column "users.id"
rake aborted!
PG::Error: ERROR: type "hstore" does not exist
LINE 1: ...p NOT NULL, "updated_at" timestamp NOT NULL, "data" hstore)
^
: CREATE TABLE "users" ("id" serial primary key, "first_name" character varying(255), "last_name" character varying(255), "email" character varying(255), "headline" character varying(255), "is_email_confirmed" boolean DEFAULT 'f', "profile_pic_url" character varying(255), "is_active" boolean DEFAULT 't', "fb_user_id" character varying(255), "fb_token" character varying(255), "is_reachable_on_fb" boolean DEFAULT 't', "linkedin_id" character varying(255), "linkedin_token" character varying(255), "linkedin_secret" character varying(255), "linkedin_public_profile_url" character varying(255), "linkedin_summary" character varying(255), "login_hash" character varying(255), "is_work_updated" boolean DEFAULT 'f', "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, "data" hstore)
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:654:in async_exec' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:654:inblock in execute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:280:in block in log' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/notifications/instrumenter.rb:20:ininstrument'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:275:in log' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:653:inexecute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/schema_statements.rb:170:in create_table' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:466:inblock in method_missing'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:438:in block in say_with_time' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/benchmark.rb:295:inmeasure'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:438:in say_with_time' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/migration.rb:458:inmethod_missing'
/Users/bhilkert/Dropbox/code/spokely/db/schema.rb:101:in block in <top (required)>' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/schema.rb:50:ininstance_eval'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/schema.rb:50:in define' /Users/bhilkert/Dropbox/code/spokely/db/schema.rb:14:in<top (required)>'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/dependencies.rb:245:in load' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/dependencies.rb:245:inblock in load'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/dependencies.rb:236:in load_dependency' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/dependencies.rb:245:inload'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/railties/databases.rake:366:in block (3 levels) in <top (required)>' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:incall'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in block in execute' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:ineach'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in execute' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:158:inblock in invoke_with_call_chain'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in mon_synchronize' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:ininvoke_with_call_chain'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:144:in invoke' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/railties/databases.rake:479:inblock (3 levels) in <top (required)>'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in call' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:inblock in execute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in each' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:inexecute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:158:in block in invoke_with_call_chain' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:inmon_synchronize'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:in invoke_with_call_chain' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:144:ininvoke'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/railties/databases.rake:459:in block (3 levels) in <top (required)>' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:incall'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in block in execute' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:ineach'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in execute' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:158:inblock in invoke_with_call_chain'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in mon_synchronize' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:ininvoke_with_call_chain'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:144:in invoke' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/railties/databases.rake:524:inblock (3 levels) in <top (required)>'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:in call' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:205:inblock in execute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:in each' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:200:inexecute'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:158:in block in invoke_with_call_chain' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:inmon_synchronize'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:151:in invoke_with_call_chain' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/task.rb:144:ininvoke'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:116:in invoke_task' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:inblock (2 levels) in top_level'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:in each' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:94:inblock in top_level'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:133:in standard_exception_handling' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:88:intop_level'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:66:in block in run' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:133:instandard_exception_handling'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/lib/rake/application.rb:63:in run' /Users/bhilkert/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/rake-0.9.2.2/bin/rake:33:in<top (required)>'
/Users/bhilkert/.rbenv/versions/1.9.2-p290/bin/rake:19:in load' /Users/bhilkert/.rbenv/versions/1.9.2-p290/bin/rake:19:in

'
Tasks: TOP => db:schema:load

I also tried adding the following to spec_helper.rb:

  require 'activerecord-postgres-hstore'
  require 'activerecord-postgres-hstore/activerecord'

Still get the same thing. Is there something I'm missing setting this up for testing?

error on migration

Running the latest from git I get:

rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  could not access file "$libdir/hstore": No such file or directory
: /* $PostgreSQL: pgsql/contrib/hstore/hstore.sql.in,v 1.11 2009/06/11 18:30:03 tgl Exp $ */

please advise. thanks!

undefined method add_runtime_options!

The railtie is triggering an undefined method exception when trying to load rails/generators

Commenting out the requires of the generator code, along with removal/commenting of the Setup generator allows the app to boot correctly.

Running rails 3.2.5.

Rails 3.2.9 Ruby 1.9.3-p362 gem install activerecord-postgresql-adapter

When I do a bundle, everything runs smooth. When I do rails g hstore:setup or rails s, for that matter anything where the environment is loaded. I get the following error.

/Users/evansparkman/.rvm/gems/ruby-1.9.3-p362@aqualogger/gems/activesupport-3.2.9/lib/active_support/dependencies.rb:251:in require': Please install the postgresql adapter:gem install activerecord-postgresql-adapter` (cannot load such file -- java) (LoadError)

Gem List:
activerecord-jdbc-adapter (1.2.5)
activerecord-jdbcpostgresql-adapter (1.2.5)
activerecord-postgres-hstore (0.5.0)
activerecord-postgresql-adapter (0.0.1)
pg (0.14.1)

Thoughts?

More Convention, Less Configuration

In the README usage example, why have serialize :data, ActiveRecord::Coders::Hstore as the standard way of using the gem? It makes working with the gem more cumbersome and error-prone because you need to remember to set a {} before using the attr or you get an error.

In my opinion, serialize :data, ActiveRecord::Coders::Hstore.new should be the default usage, which uses a default value of {} or HashWithIndifferentAccess.new unless something different is specified in the constructor. What are your thoughts?

Problem inserting multiple keys at once with ActiveRecord 3.1

ruby-1.9.2-p180-good :014 > Person.create! :data => { :name => 'joe', :foo => false }
   (0.3ms)  BEGIN
  SQL (1.2ms)  INSERT INTO "people" ("created_at", "data", "name", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["created_at", Sun, 06 Nov 2011 10:36:20 PST -08:00], ["data", "('name'=>'joe') || ('foo'=>'false')"], ["name", nil], ["updated_at", Sun, 06 Nov 2011 10:36:20 PST -08:00]]
   (0.1ms)  ROLLBACK
ActiveRecord::StatementInvalid: PGError: ERROR:  Syntax error near '|' at position 16
: INSERT INTO "people" ("created_at", "data", "name", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:1021:in `get_last_result'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:1021:in `exec_cache'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `block in exec_query'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:244:in `block in log'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activesupport/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:239:in `log'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:590:in `exec_query'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:63:in `exec_insert'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:90:in `insert'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/relation.rb:70:in `insert'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/persistence.rb:313:in `create'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/timestamp.rb:51:in `create'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/callbacks.rb:268:in `block in create'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activesupport/lib/active_support/callbacks.rb:390:in `_run_create_callbacks'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activesupport/lib/active_support/callbacks.rb:81:in `run_callbacks'
... 6 levels...
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/persistence.rb:57:in `save!'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/validations.rb:56:in `save!'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/attribute_methods/dirty.rb:33:in `save!'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/transactions.rb:246:in `block in save!'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/transactions.rb:208:in `transaction'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/transactions.rb:246:in `save!'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/activerecord/lib/active_record/validations.rb:41:in `create!'
  from (irb):14
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/railties/lib/rails/commands/console.rb:45:in `start'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/railties/lib/rails/commands/console.rb:8:in `start'
  from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-12d451498208/railties/lib/rails/commands.rb:40:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'/Users/joe/.rvm/gems/ruby-1.9.2-p180-good/bin/bundle


ruby-1.9.2-p180-good :015 > Person.create! :data => { :name => 'joe' }
   (0.3ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "people" ("created_at", "data", "name", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["created_at", Sun, 06 Nov 2011 10:37:10 PST -08:00], ["data", "('name'=>'joe')"], ["name", nil], ["updated_at", Sun, 06 Nov 2011 10:37:10 PST -08:00]]
   (0.2ms)  COMMIT
 => #<Person id: 2, name: nil, data: {:name=>"joe"}, created_at: "2011-11-06 18:37:10", updated_at: "2011-11-06 18:37:10"> 

Non Standard Env DB

We are trying to use activerecord-postgres-hstore with a secondary DB which we define in our database.yml file like:

properties:
adapter: postgresql
host: 127.0.0.1
database: hstorage_dev
encoding: unicode
username: postgres
password:
pool: 5

Then in our model (Mls::Property) we have the following:

class Mls::Property < ActiveRecord::Base
establish_connection :properties
#feature_store is an hstore column
end

Now this is a DB that is secondary, our primary DB for the regular rails development/production envs are MySQL and we have a secondary PostgreSQL db that we do not run migrations for in this app, it is read only.

So, when we try and do Mls::Property.first.feature_store we get the column back as a string not a hash

also:

Mls::Property.columns_hash['feature_store']
=> #<ActiveRecord::ConnectionAdapters::PostgreSQLColumn:0x10db12520 @scale=nil, @precision=nil, @primary=false, @default=nil, @null=true, @type=nil, @name="feature_store", @limit=nil, @sql_type="hstore">

I am wondering if this is due to the fact that the tables for this db are not in our schema.rb file?

How can we get this attribute back as a hash instead of a string automatically?

For now I am trying to do something like:

def features_store
feature_store.from_hstore
end

But this feels like a pretty bad hack, and what would we do when we actually want to make this app read and write to that DB not just read?

Any ideas on how to make it recognize the column as hstore automatically?

~ Tom

rails 3.0 btw.

Use outside of Rails

I'm trying to figure out how to use this gem outside of Rails (and without using Bundler). I've created a table with an hstore column but when I try to use that column in Ruby, ActiveRecord is just treating it as a String and is not converting it to a Hash. If I explicitly call #from_hstore on the column then it gives the hash, so at least part of the gem is loading.

I'm using ruby 1.9.3, and the gems activerecord-postgres-hstore (0.3.0) and activerecord (3.2.3).

Any ideas? The code I'm using is below.

Thanks,
Geoff

#!/usr/bin/env ruby
require 'rubygems'
require 'active_record'
require 'activerecord-postgres-hstore'
require 'activerecord-postgres-hstore/activerecord'

ActiveRecord::Base.establish_connection(
  :adapter => 'postgresql',
  :database => 'geoffk',
  :host => '/tmp'
)

class Restaurant < ActiveRecord::Base
  # I tried using this but the Hstore coder does not exist
  # serialize :amenities, ActiveRecord::Coders::Hstore
end

r = Restaurant.first

puts r.amenities.inspect
#=> "\"wi-fi\"=>\"false\", \"parking\"=>\"private lot\""

puts r.amenities.class.name
#=> String

puts r.amenities.from_hstore
#=> {"wi-fi"=>"false", "parking"=>"private lot"}

wrong constant name Activerecord-postgres-hstore

During rake db:prepare

Rake aborted!

/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/require_reloader-0.1.3/lib/require_reloader.rb:49:in const_defined?' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/require_reloader-0.1.3/lib/require_reloader.rb:49:in_callback_before_47'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:429:in _run__621037826__prepare__4__callbacks' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:405:insend'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:405:in __run_callback' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:385:in_run_prepare_callbacks'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:81:in send' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:81:inrun_callbacks'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/actionpack-3.2.11/lib/action_dispatch/middleware/reloader.rb:74:in prepare!' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/actionpack-3.2.11/lib/action_dispatch/middleware/reloader.rb:48:inprepare!'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/application/finisher.rb:47
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/initializable.rb:30:in instance_exec' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/initializable.rb:30:inrun'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/initializable.rb:55:in run_initializers' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/initializable.rb:54:ineach'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/initializable.rb:54:in run_initializers' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/application.rb:136:ininitialize!'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/railtie/configurable.rb:30:in send' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/railtie/configurable.rb:30:inmethod_missing'
/Users/tim/Documents/digital_dialogue/source/chrysler/config/environment.rb:5
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:in require' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:inrequire'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:236:in load_dependency' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:inrequire'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/application.rb:103:in require_environment!' /Users/tim/.rvm/gems/ree-1.8.7-2012.02/gems/railties-3.2.11/lib/rails/application.rb:297:ininitialize_tasks'
/Users/tim/.rvm/gems/ree-1.8.7-2012.02/bin/ruby_noexec_wrapper:14

Setting keys via a form

Can't seem to use Rails form helpers with this gem. Here is the setup

class Site < ActiveRecord::Base
  serialize :data, ActiveRecord::Coders::Hstore
  attr_accessible :data, :name
end

# Also ran this migration
execute "CREATE EXTENSION IF NOT EXISTS hstore"

In the view:

= form_for @site do |f|
  = f.text_field :name
  = f.fields_for :data do |d|
    = d.text_field :seo_page_title
    = d.text_field :seo_keywords
    = d.text_field :seo_description
  = f.submit 

The page displays the fields without any issues. But when I save the form none of the data fields are recorded. I even tried to be explicit in the controller update action site.data = params[:site][:data] but for some reason it's just not saving anything. What am I missing?

Trying to make to_hstore in a COPY from STDIN

I am trying to use the gem to try and get some data into a table with an hstore column. The data is in a CSV file. Obviously I could insert the records one at a time and that works perfectly but for performance reasons I would prefer to use the COPY command.

My stragegy is to run the file though CSV/FasterCSV and then on each line do this

   @new_batch  << "#{@batch.id}\t#{row.to_hstore}\v\n"

This creates a new batch file and to guard against having data with common delimiters I am using \t for delimiter and \v for quote The copy command is done like this

COPY imports (id,data) FROM STDIN WITH CSV QUOTE E'\v' DELIMITER E'\t'

I have tried various QUOTE and DELIMITER options but none of them seem to work.

From what I can tell this is because to_hstore is not properly quoting the data.

For example see this hash

{"cancelled"=>"0",
 "internet"=>"0",
 "sap_code"=>"XXXXXXX",
 "carry_over"=>"0",
 "traffic_date"=>"2012-01-09 00:00:00",
 "dealer_name"=>"XXXXXXX",
 "walk_in"=>"0",
 "model_name"=>"300C 3.0L CRD 5A",
 "family_name"=>"LE 300C",
 "deliveries"=>"0",
 "demo"=>"0",
 "orders"=>"0",
 "model_code"=>"272.4L2.0",
 "product_name"=>"Fiat",
 "phone"=>"0",
 "valuation"=>"0",
 "dc_model_id"=>nil}

This turns into

cancelled=>0,internet=>0,sap_code=>XXXXX,carry_over=>0,traffic_date=>"2012-01-09 00:00:00",dealer_name=>"XXXXX",walk_in=>0,model_name=>"300C 3.0L CRD 5A",family_name=>"LE 300C",deliveries=>0,demo=>0,orders=>0,model_code=>272.4L2.0,product_name=>Fiat,phone=>0,valuation=>0,dc_model_id=>NULL"

Notice that the model_code is not being quoted. Postgres complains about that piece of data and complains at 4.

Support for .select()?

Is there a way to query for only specific attributes in my hstore field?

When I try using Thing.where(...).select([:column1, :column2]), I get an error from PostgreSQL saying "column things.column1 does not exist". I know that the syntax for hstore is "SELECT attributes->'column1' AS column1 FROM things", but how do I construct this query using activerecord-postgres-hstore?

Doesnt play nice with JSON serialization

If one uses the new Rails 3.1 serialization coder:

class PhotoMetadata < ActiveRecord::Base
  serialize :exif,     JSON
end

And has this gem loaded then any usages of a PhotoMedata blows up because YAML is being stored it is specified to use the JSON decoder, so the JSON parser blows up.

If one comments out the monkeypatch of arel_attributes_values in lib/activerecord-postgres-hstore/activerecord.rb then all is swell. So I know its related to that method directly.

I currently dont need to filter on hstore keys, so I can fork this repo and use a commented-out version, but going forward it might be an issue for others.

Modifying a hash in a hstore column does not set the column as dirty

Hi

I have come across the following issue. Assuming that Participant is an ActiveRecord model with a hstore column, after an initial save of a hash in the column, any subsequent addition of elements to the column does not mark the column as changed.

To illustrate:

p = Participant.new
p.data ||= {}
p.data['field1'] = 5 
p.data_changed?.should == true

#this save inserts the right data into the database
p.save!
p.data['field2'] = 'new field test' 

#this fails
p.data_changed?.should == true

#any subsequent save does not actually result in an update to the db
p.save!

The result of this is subsequent calls to save calls on the model does not result in a database update.

Looking online I managed to dig up a similar issue related to serialized columns - https://rails.lighthouseapp.com/projects/8994/tickets/360-dirty-tracking-on-serialized-columns-is-broken. Is the reason the same ? Is the suggested workaround of using the "attribute_will_change!" method the best solution ?

Thanks for helping!

Versions >= 0.7.0 introduce error preventing tables with hstore columns from dumping properly to the schema file

Versions 0.7.0, 0.7.1, and 0.7.2 introduce an error in which tables with hstore columns are not dumped to the schema file, replaced with an error message such as:

# Could not dump table "services" because of following StandardError
#   Unknown type 'hstore' for column 'eligibility'

I am using the postgres template database setup rather than the config.active_record.schema_format = :sql setup.

The problem is not present in 0.6.0

Gem does not work without git repo

In my app I cannot specify gem 'activerecord-postgres-hstore' without adding the github repo.

Although I can bundle install without any issues, I can no longer migrate hstore field types - it tells me that hstore is an undefined method.

As soon as I add git: 'git://github.com/softa/activerecord-postgres-hstore.git' to my Gemfile everything just works. Perhaps the version that resides on rubygems needs to be updated?

FWIW, this is an issue for me because I will be deploying this app on a PaaS and I have yet to encounter any that support git gems.

?| Operator does not exist

I'm trying to use the ?| operator on PostgreSQL 9.0.4 on Mac OS X (after running rails g hstore:setup

and I get this error:

ActiveRecord::StatementInvalid: PGError: ERROR:  operator does not exist: hstore ?| text[]

This is the query that I'm trying to run:

Video.where("tags ?| ARRAY['lonely', 'abc']")

The generated SQL is

SELECT "videos".* FROM "videos" WHERE (tags ?| ARRAY['lonely', 'abc'])

TIA!

Default value for hstore column

It would be nice to set default value as an empty array with hstore(array[]::varchar[]). In that case you can smoothly use store_accessor, which is really cool.

Getting ActiveRecord::HstoreTypeMismatch with valid Hash.

I just started using this gem along with Rails 3.2.9. I'm trying to get it to work the accessor methods. I'm not sure if it's an issue with Rails or with this gem but here's the issue.

I installed the Gem, ran the setup I added the serialize statement to my model. I also added the store_accessor to my column like so:

class App < ActiveRecord::Base
  serialize :properties, ActiveRecord::Coders::Hstore

  store_accessor :properties, [:author]
  ...
end

In the rails console I ran the following:

1.9.3p327 :001 > a = App.first
  App Load (3.1ms)  SELECT "apps".* FROM "apps" LIMIT 1
 => #<App id: 1, name: "Some Name", properties: {"author"=>"Leo", "version"=>"1.0"}> 
1.9.3p327 :002 > a.author
 => nil 
1.9.3p327 :003 > a.author = "Chuck"
 => "Chuck" 
1.9.3p327 :004 > a.save!
   (0.5ms)  BEGIN
  App Exists (0.9ms)  SELECT 1 AS one FROM "apps" WHERE ("apps"."name" = 'Some Name' AND "apps"."id" != 1) LIMIT 1
   (0.6ms)  UPDATE "apps" SET "properties" = 'author=>Leo,version=>1.0,author=>Chuck', "updated_at" = '2012-12-06 23:10:18.689675' WHERE "apps"."id" = 1
   (0.5ms)  COMMIT
 => true 
1.9.3p327 :005 > a.author
 => nil 
1.9.3p327 :006 > a
 => #<App id: 1, name: "Some Name", properties: {"author"=>"Chuck", "version"=>"1.0"}> 

So the attribute is updating but I can't access the getter for the attribute.

Now I was researching this issue a bit and found that Rails has a store method that does the serializing but instead of using ActiveRecord::Coders::Hstore, it uses Hash. I tried using said method and the whole thing breaks when trying to save.

This is the code in store method for Rails

store.rb

module ClassMethods
  def store(store_attribute, options = {})
    serialize store_attribute, Hash
    store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
  end

  def store_accessor(store_attribute, *keys)
    Array(keys).flatten.each do |key|
      define_method("#{key}=") do |value|
        send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash)
        send(store_attribute)[key] = value
        send("#{store_attribute}_will_change!")
      end

      define_method(key) do
        send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash)
        send(store_attribute)[key]
      end
    end
  end
end

I get the following in the Rails console:

Loading development environment (Rails 3.2.9)
1.9.3p327 :001 > a = App.first
  App Load (3.1ms)  SELECT "apps".* FROM "apps" LIMIT 1
 => #<App id: 1, name: "Some Name", properties: "\"author\"=>\"Leo\", \"version\"=>\"1.0\""> 
1.9.3p327 :002 > a.author
 => nil 
1.9.3p327 :003 > a.author = "Chuck"
 => "Chuck" 
1.9.3p327 :004 > a.save!
   (0.4ms)  BEGIN
  App Exists (0.8ms)  SELECT 1 AS one FROM "apps" WHERE ("apps"."name" = 'Some Name' AND "apps"."id" != 1) LIMIT 1
   (0.3ms)  ROLLBACK
ActiveRecord::HstoreTypeMismatch: properties must have a Hash or a valid hstore value (---
:author: Chuck
)
    from /Users/leo/.rvm/gems/ruby-1.9.3-p327@developer/gems/activerecord-postgres-hstore-0.4.1/lib/activerecord-postgres-hstore/activerecord.rb:159:in `quote_with_hstore'
...

Important

Notice that I reloaded the rails console from the run before I switched to using the store method. The value of author in properties was changed back to "Leo" instead of "Chuck"

I also happened to find a quick fix for the getter on the first option ( the one using serialize from ActiveRecord::Coders)

I modified the line in store.rb that has

send(store_attribute)[key] to => send(store_attribute)["#{key}"]

and I was able to access the attributes. Still it didn't update after saving the model leaving and starting the console back.

Any insight on this?

version 0.5.0 is installing jdbc drivers on plain ruby

Hi,

I just ran a bundle update, and am seeing the activerecord-jdbc-adapter included as a dependency.

I am not running jruby, and it's breaking my rails app at runtime.

ruby -v
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]

Just wanted to give a headsup.

Support for hstore functions

Is there any way to use the hstore functions (skeys, svals, etc) via ActiveRecord::Query? I have a class method on my model to return the list of distinct keys used in the hstore attribute:

sql = "SELECT DISTINCT key FROM ( SELECT skeys(data) AS key from \"products\" ) AS keys"

The challenge I'm running into is adding things like pagination and matching on top of this method, and I'm hoping I'm missing something in terms of a workable approach. Any pointers are much appreciated.

Can't find hstore for db:test:prepare

I have seen the other tickets, I have set format to sql in the application.rb, I have made sure the migration timestamps have the right order, I have manually enabled hstore in template1 and I am still having this problem

rails-3.2.9
postgres.app
macosx 10.8.2

Use active record as dependency instead of rails

ActiveRecord can be used with other frameworks like Sinatra. Why is this gem dependant on whole rails? Dependency to active record should be enough, even if you're using active support, because its dependency of active record.

Values with new lines have double quotes wrapped around them after save

I'm a bit stuck with this one. If I persist a string with a \n in, it's returned with double quotes wrapped around the entire string. I've tried applying the patches that a few people have written to escape values correctly, but they're not doing what I'd expect.

The following spec should illustrate the problem:

it "should not change values with line breaks" do
  input = { "a" => "foo\n\nbar" }
  output = input.to_hstore
  output.from_hstore.should eq(input)
end

Me or a need for an update to the README?

Rails: 3.2.6. I had to use the serializer on the gem from rubygems.org even though the README implies that you would only need to do that if you are using the 'development' version. Do we always need to use the serializer now? If so perhaps a documentation update?

The model that tripped me up for a minute at first:

class Page < ActiveRecord::Base
  validates_presence_of(:type, :data); belongs_to(:user, readonly: true)
end

It was a simple model, yes it was using a OpenStruct or SuperStruct (my own beefed up custom version of OpenStruct) but I had added [to|from]_hstore to work around potential issues... Even when I was working with a raw hash I would always get:

INSERT INTO "pages" ("data", "type") VALUES ($1, $2) RETURNING "id" [["data", {"slug"=>"Test"}], ["type", "page"]]
ActiveRecord::StatementInvalid: PG::Error: ERROR: Syntax error near 's' at position 4

That is, until I implemented the serializer and it started turning it properly.

Setting key values inside a callback

I am trying to process some files and cache the resulting URLs in my data hash in a before_save callback

Given that this is a callback and I don't want to trigger infinite stack, I am using update_column()

def my_before_save_method
  self.data['waveform_master_url'] = 'whatever'
  self.update_column(:data, data)
end

Of course running this returns a nil error, because in this case data.blank? == true. So I try to be sneaky and set a default value:

def my_before_save_method
  self.update_column(:data, { 'waveform_master_url' => '' }) if self.data.blank?
  self.data['waveform_master_url'] = 'whatever'
  self.update_column(:data, data)
end

That gets me a prompt smack on the wrist:

ActiveRecord::StatementInvalid: PG::Error: ERROR:  Syntax error near '-' at position 4
LINE 1: UPDATE "tracks" SET "data" = '---

It seems that I would need to actually set the value using yaml string or something, but at this point I thought UGH there has to be a way that sucks a whole lot less. So here I am :)

Select Distinct in Rails Associations

Looks like SELECT DISTINCT doesn't work if you try to include the hstore field in the query, ie:

=> SELECT DISTINCT "services".* FROM "services";
ERROR: could not identify an equality operator for type hstore

Rails executes SELECT DISTINCT on a joined modeles when I am trying to destroy an instance which is associated (by habtm in my case).

Is this known issue? Is there an easy workaround?

Compatibility with newer versions of bundler (> 1.1.0)

Apparently bundler versions greater than 1.1.0 have started converting gem names to require names by changing dashes to slashes so if you just add activerecord-postgres-hstore to your Gemfile as suggested in the Readme bundler tries to require activerecord/postgres/hstore. According to a guy in #bundler on IRC it's a rubygems convention for gem files to be namespaced this way.

Something is wrong with quotes in unicode values

Hi! Happy New Year!

I just want to migrate from serialization to hstore and get the strange error:

irb(main):012:0> t = Translation.find(50)

The old serialization:

irb(main):013:0> t.languages
=> {:ru=>"Скидка купоны/подарочные билеты путешествия", :en=>"Travel discount coupons/gift tickets", :zh=>"旅游折扣券/赠票", :fr=>"Voyage rabais coupons cadeaux billets", :de=>"Rabatt-Gutscheine/Gift Fahrkarten"}

The new hstore:

irb(main):014:0> t.lang = { 'zh' => t.languages[:zh] }
=> {"zh"=>"旅游折扣券/赠票"}
irb(main):015:0> t.save

(0.3ms) UPDATE "translations" SET "lang" = 'zh=>旅游折扣券/赠票', "updated_at" = '2013-01-02 00:46:35.002511' WHERE "translations"."id" = 50
ERROR: Syntax error near '?' at position 7
LINE 1: UPDATE "translations" SET "lang" = 'zh=>旅游折扣券/赠票', "u...

ArgumentError: invalid byte sequence in UTF-8
from /Users/incubus/.rvm/gems/ruby-1.9.3-p362/gems/activerecord-3.2.9/lib/active_record/connection_adapters/postgresql_adapter.rb:1141:in ===' from /Users/incubus/.rvm/gems/ruby-1.9.3-p362/gems/activerecord-3.2.9/lib/active_record/connection_adapters/postgresql_adapter.rb:1141:intranslate_exception'

I don't see quotes in SET "lang" = 'zh=>旅游折扣券/赠票' and it also breaks postgresql adapter error output.

It works fine with ASCII:

irb(main):016:0> t.lang = { 'en' => t.languages[:en] }
=> {"en"=>"Travel discount coupons/gift tickets"}
irb(main):017:0> t.save
(0.2ms) UPDATE "translations" SET "lang" = 'en=>"Travel discount coupons/gift tickets"', "updated_at" = '2013-01-02 00:48:39.191811' WHERE "translations"."id" = 50
=> true

Nested hashes don't get parsed

For instance, if I store

"location"=>{"id"=>"106078429431815", "name"=>"London, United Kingdom"}

and then access it again, I get back a string, not a hash

"location"=> "{\"id\"=>\"106078429431815\", \"name\"=>\"London, United Kingdom\"}"

trouble passing ? params to where

When using hstore, I can do this:

Team.where("data @> 'hstore_key_name=> #{some_string}'")

And I can also do this:

Team.where(%Q{data @> 'hstore_key_name=> #{some_string}'})

And with an int I can do this:

Team.where(%Q{data @> 'hstore_key_name=> ?'}, some_int)

but I can't seem to get this to work without a syntax error:

Team.where(%Q{data @> 'hstore_key_name=> ?'}, some_string)

I think I'm missing another level of quotes, but don't know how to add them.. Any ideas on how I can make it work? In a nutshell I want to avoid sql injection issues as much as possible.

2 dimensional hash returned as string

I'm usign the hstore solution to store a time-table in the database. I enabled hstore for posgresql and made a new field availability in my table of the type hstore.

I added this to my model :

serialize :availability, ActiveRecord::Coders::Hstore

When I submit the form he submit the following value for availability:

"availability"=>{"monday"=>{"morning"=>{"start"=>"10:00", "end"=>"00:00"}, "lunch"=>{"start"=>"09:00", "end"=>"11:00"}, "evening"=>{"start"=>"12:00", "end"=>"21:00"}}}

Now when I want to fetch the start and end for the morning of monday I tried to navigate trough the has, but when I call

@profile.availability["monday"]

it returns me back a string of the next format

"{\"morning\"=>{\"start\"=>\"10:00\", \"end\"=>\"00:00\"}, \"lunch\"=>{\"start\"=>\"09:00\", \"end\"=>\"11:00\"}, \"evening\"=>{\"start\"=>\"12:00\", \"end\"=>\"21:00\"}}"

How can I convert this back to a Hash so I can get the data out of it by navigating in the hash?

Error running Rspec/FactoryGirl after updating from 0.7.4 to 0.7.5

Updating gem from 0.7.4 to 0.7.5 causes all my tests to break. Specifically on the Factory for the model that has the hstore attribute

let(:first_box) { create(:box, client_id: client.id) }
     NoMethodError:
       undefined method `to_hstore' for {}:Hash
FactoryGirl.define do
  factory :box do
    client_id 1
    friendly_name { Faker::Name.name }
  end
end

The attribute for the box model is called metadata. I'm a bit confused because I'm not using to_hstore anywhere. The tests pass just fine using this gem's version 0.7.4. When I updated to 0.7.5 the tests started failing.

Boolean type parsing

Hi,
something like {'x'=>true}.to_hstore is "x"=>"true"

I believe this is not correct, because if you deserialize it back, it becomes {'x'=>'true'} #'true' is a string value, not boolean.
Another problem is querying

where("hstore_column @> (:key => :value)", key: key, value: true) # currently you have to pass in true.to_s

Postgres uses 't' to represent boolean true values.

I could implement this if you agree with the above.

Hstore column changes not reflected in dirty attributes

Updates to an hstore attribute don't seem to be reflected in a model's dirty attributes. For example:

f = Foo.find(id)
f.hstore_column = {}
f.save
f = Foo.find(id)
f.hstore_column = {'bar' => 'foobar'}
f.hstore_column.changed? => false

default value is erroneously reused between objects

regarding new feature added in 5c2efd4

the same empty hash is reused for all objects.

here's the behavior i see in my app. if you can't reproduce this yourself in your own simple tests let me know and i'll put together an example app demonstrating the problem.

>> one = Foo.find(1)
>> two = Foo.find(2)
>> one.metadata
{}
>> two.metadata
{}
>> one.metadata['foo'] = 5
>> one.save
>> one.metadata
{"foo" => "5"} # value is a string because it was properly converted when being saved to DB
>> two.metadata
{"foo" => 5 } # value is an int -- @default empty hash value got permanently changed in memory and reused across obejects
>> two.reload.metadata
{"foo" => 5 }

rake db:test:prepare errors

After bumping to the lastest version (0.7.5), schema.rb looks fantastic (thanks!); however, now I'm having difficulty in preparing my test database.

It looks like my test environment doesn't have the gem accessible (but it should, as stated in my Gemfile). I've tried poking around and manually creating the hstore extension in my test database with no avail.

Any help would be really appreciated! Thanks in advance!

rake aborted!
PG::Error: ERROR:  type "hstore" does not exist
LINE 1: ...y, "name" character varying(255) NOT NULL, "data" hstore NOT...
                                                             ^
: CREATE TABLE "object_types" ("id" serial primary key, "name" character varying(255) NOT NULL, "data" hstore NOT NULL, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) 

HStore parser

Howdy,

I wrote a cautious and thoroughly implemented parser for the HStore spec. I'm working on releasing it as a gem, and I'd like to work with you to make it available in ActiveRecord.

My implementation for Sequel is here and is based on inspection of the C source code: https://github.com/pvh/sequel-hstore

Can I persuade you to adopt my parser if I make the interface sane?

-p

Bundler notice

When running bundle install I get the following notice:

activerecord-postgres-hstore at bundler/gems/activerecord-postgres-hstore-15958f2a736d
did not have a valid gemspec.
This prevents bundler from installing bins or native extensions, but that may not affect its
functionality.
The validation message from Rubygems was:
  ["README.textile"] are not files

Rails 3.2.3
Gem activerecord-postgres-hstore from master branch.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.