Git Product home page Git Product logo

nested-hstore's Introduction

Nested Hstore

Store nested hashes and other types in ActiveRecord hstores

Overview

Postgres hstores offer a number of benefits, but they don't natively support multi-level data. Nested Hstore adds this support to ActiveRecord, letting you treat an hstore like a NoSQL-like document.

Hstore functions are still supported at the root level.

It also lets you store data types other than hashes in an hstore. All of the following values will be returned verbatim:

class User < ActiveRecord::Base
  serialize :my_property, ActiveRecord::Coders::NestedHstore
end

# Nested hash
user.my_property = {
  'name' => 'Jane Doe',
  'comment_ids' => [34, 67, 82],
  'location' => {
    'id' => 15,
    'city' => 'San Francisco',
    'state' => 'CA'
  }
}

# Array
user.my_property = [34, 67, 82]

# Array of nested hashes
user.my_property = [
  {
    'id' => 15,
    'username' => 'janedoe'
  },
  {
    'id' => 16,
    'username' => 'johndoe'
  }
]

# Boolean
user.my_property = true

# Integer
user.my_property = 43

# Float
user.my_property = 43.1

# String
user.my_property = 'janedoe'

Installation

If you're using ActiveRecord 2.x or 3.x, set up activerecord-postgres-hstore if you haven't already. This isn't necessary for ActiveRecord 4.x.

Include it in your Gemfile:

gem 'nested-hstore'

Serialize each property using ActiveRecord::Coders::NestedHstore:

class User < ActiveRecord::Base
  serialize :my_property, ActiveRecord::Coders::NestedHstore
end

Testing

Nested Hstore is tested against ActiveRecord 3 and 4. If you'd like to submit a PR, please be sure to use Appraisal to test your changes in both contexts:

appraisal rspec

License

Nested Hstore is released under the MIT License. Please see the MIT-LICENSE file for details.

nested-hstore's People

Contributors

bcavileer avatar chibicode avatar jordan-thoms avatar tombenner 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nested-hstore's Issues

numeric and boolean values at 0-th level of hash are retrieved/saved as string

This is a copy paste case from my console
p.details = {"b"=>2, "c"=>true, "bb" =>3.2, "t"=>"am", "u"=>{"id"=>15, "us"=>"asd", "d"=>true}}
=> {"b"=>2, "c"=>true, "bb"=>3.2, "t"=>"am", "u"=>{"id"=>15, "us"=>"asd", "d"=>true}}
2.0.0p353 :028 > p.save
(0.3ms) BEGIN
SQL (1.9ms) UPDATE "products" SET "details" = $1, "updated_at" = $2, "coordinates" = $3, "mass_relevance" = $4 WHERE "products"."id" = 4453 ["details", ""b"=>"2","c"=>"true","bb"=>"3.2","t"=>"am","u"=>"{\"id\":15,\"us\":\"asd\",\"d\":true}","TYPE"=>"HASH""], ["updated_at", Tue, 08 Apr 2014 05:27:08 UTC +00:00], ["coordinates", ""], ["mass_relevance", ""] COMMIT
=> true
2.0.0p353 :029 > p.reload
Product Load (1.2ms) SELECT "products".* FROM "products" WHERE "products"."id" = $1 LIMIT 1 [["id", 4453]]
=> #<Product id: 4453, brand: nil, entity_path: nil, market: nil, market_rank: nil, name: nil, property_code: nil, property_rank: nil, category: nil, created_at: "2014-04-08 05:21:15", updated_at: "2014-04-08 05:27:08", feed_id: nil, expired: nil, coordinates: nil, mass_relevance: nil, short_description: nil, details: {"b"=>"2", "c"=>"true", "t"=>"am", "u"=>{"id"=>15, "us"=>"asd", "d"=>true}, "bb"=>"3.2"}>
2.0.0p353 :030 > p.details
=> {"b"=>"2", "c"=>"true", "t"=>"am", "u"=>{"id"=>15, "us"=>"asd", "d"=>true}, "bb"=>"3.2"}

ActiveSupport::JSON.decode is casting my phone numbers into integers

I have phone numbers stored in a hash {"LOCATION_PHONE" => "123-456-7890"}

ActiveSupport::JSON.decode("123-456-7890")
=> 123

    def decode_json_if_json(value)
      begin
        ActiveSupport::JSON.decode(value)
      rescue
        value
      end
    end

I'm not sure how to fix this without breaking nested-hstore.

I'm using nested-hstore because there are nested hashes in there as well ;)

Hstore Postgres 9.4

Hi there, thank you for this gem which is very useful.

My question is, how does this gem different from the nested array support in posgres 9.4? I noticed that the default hstore is storing nested element as string and not the original data type. Is there any other differences? Thank you in advance!

undefined method `simplified_type'

Dears,

Using Rails 4.2.0 and nested_hstore i got the below error.

Error: .rvm/gems/ruby-2.1.5/gems/activesupport-4.2.0/lib/active_support/core_ext/module/aliasing.rb:32:in alias_method': undefined methodsimplified_type' for class `ActiveRecord::ConnectionAdapters::PostgreSQLColumn' (NameError)

please, help

issues with saving and using nested-hstore on a large-scale app

Hey,
I've been wondering if you gem has been used on any large-scale applications ? I'm a little concerned because of the age of the gem and community. I love the idea, but I've been having some issues with it:

When I load an instance of a model, which has nested-hash properties and save it (without changing anything), active model will update the whole record, although nothing has been changed.

Have you tested this?

Confusion with string/symbol keys

I just upgraded to 0.0.5 to 0.1.2, and noticed some specs failing. With my Story model like:

class Story < ActiveRecord::Base

    serialize :data, ActiveRecord::Coders::NestedHstore` I had a spec like:

    def twitter_title
      data && data["twitterDescription"] ? data["twitterDescription"] : title
    end

end

Then my spec like:

story = create(:story, title: "This is the title", data: {twitterDescription: "Title"})
story.twitter_title.should == "Title"

This was passing before. Now it doesn't pass because story.data["twitterDescription"] == nil and story.data[:twitterDescription] == "Title".

To fix my spec, I need to change it to:

story = create(:story, title: "This is the title", data: {twitterDescription: "Title"})
story.reload
story.twitter_title.should == "Title"

Is this a bug or intended behavior? I'd prefer the previous behavior, where the output was consistent before and after the model had been reloaded. The keys were always strings and I could code for that.

To clarify: if you set a hash with string keys, they stay string keys before and after a model reload. If you set a hash with symbol keys, they'll be symbols until you reload the model and then they'll be strings.

Array data type is lost when upgrading gem from 0.0.1 to 0.0.2.

Array data type is lost when upgrading gem from 0.0.1 to 0.0.2.

For e.g.:

ActiveRecord model instance arobj has a nested hstore column called data.

With this line is Gemfile.lock:
nested-hstore (0.0.2)

I get this in console, unexpectedly losing the array data type:
...
[2] » arobj.data = {"a" => [1,2,3]}
=> {
"a" => [
[0] 1,
[1] 2,
[2] 3
]
}
[3] » arobj.save
=> true
[4] » arobj.reload
...
[5] » arobj.data
=> {
"a" => "[1,2,3]"
}

With this line is Gemfile.lock:
nested-hstore (0.0.1)

I get this in console, as expected:
[2] » arobj.data = {"a" => [1,2,3]}
=> {
"a" => [
[0] 1,
[1] 2,
[2] 3
]
}
[3] » arobj.save
=> true
[4] » arobj.reload
...
[5] » arobj.data
=> {
"a" => [
[0] 1,
[1] 2,
[2] 3
]
}

Use a form to populate a deeply-nested hstore

I'm trying to figure out how to use fields in a form to populate parts of my hstore field.
Here's the data in the hstore:

custom = {
  "settings" => {
    "search" => ?,
    "start" => ?
  }
}

What works (not ideal):

<%= f.text_area :custom %>

What doesn't work (and what I need)

<%= f.text_field "custom[settings][search]" %>
<%= f.text_field "custom[settings][start]" %>

I asked this question last night on SO but no answers yet:
http://stackoverflow.com/questions/34470564/use-a-form-to-populate-a-deeply-nested-hstore

Array at level1 are serialized or deserialized as strings.

Gemfile:

gem 'pg'
gem 'activerecord-postgis-adapter'
gem 'nested-hstore'

Schema:

create_table "products", force: true do |t|
  t.string   "brand"
  t.hstore   "details"
end

Model:

class Product < ActiveRecord::Base
  serialize :details, ActiveRecord::Coders::NestedHstore
end

Failing Scenario1:

h = {brand:'Boti', details:{dateranges: [{a: :b},2]}}
p4 = Product.new
p4.details =  h[:details]
p4.save
p4.reload
h[:details][:dateranges].class
p4.details['dateranges'].class

Failing Scenario2:

h = {brand:'Boti', details:{a: [{c: :d}, 1]} }
p4 = Product.new
p4.details =  h[:details]
p4.save
p4.reload
h[:details][:a].class
p4.details['a'].class

Passing Scenario1:

h = {brand:'Boti', details:{a: {b: [{c: :d}, 1]} }}
p4 = Product.new
p4.details =  h[:details]
p4.save
p4.reload
h[:details][:a][:b].class
p4.details['a']['b'].class

Passing Scenario2:

h = {brand:'Boti', details:{a: {b: {cc:[{c: :d}, 1]}} }}
p4 = Product.new
p4.details =  h[:details]
p4.save
p4.reload
h[:details][:a][:b].class
p4.details['a']['b'].class

Nested nils

Before submitting PR I would like to know your opinion. Basically hstore does not support nils - it returns empty strings instead. But while using your gem nils are present in nested hashes. In my opinion this should be unified in one way or another. What do you think?

Trouble with nested-hstore and fixtures

Hi, I'm trying to set up some fixtures with some nested-hstore fields and I'm running into trouble. Example:

one:
  user: one
  custom:
    :name:
      :prompt: What is your name?

When running a test, I get NoMethodError: undefined methodkeys' for "{"prompt"=>"What is your name?"}":String`

It seems that the data is being saved as a String rather than as a Hash. How can I fix this?

Changing a nested Hash with Rails 4.2 leads to invalid conversion

Hi,

with Rails 4.2 the following does not work anymore

post = Post.new
post.attributes = { nested_hash: {"a"=>[{"b"=>"c"}]}}
post.save!

loaded_post = Post.find post.id

loaded_post .nested_hash['a'][0]['new_key'] = 12345
loaded_post .save!

loaded_post = Post.find post.id

loaded_post .nested_hash # value is now a string and not an Array =>  'a' => "['b' => 'c', 'new_key' => 12345]" 

regards
dieter

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.