store_complex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +25 -0
 - data/.travis.yml +15 -0
 - data/CHANGELOG.md +0 -0
 - data/CONTRIBUTORS.md +1 -0
 - data/Gemfile +4 -0
 - data/LICENSE.md +22 -0
 - data/README.md +178 -0
 - data/Rakefile +5 -0
 - data/lib/store_complex/version.rb +3 -0
 - data/lib/store_complex.rb +35 -0
 - data/store_complex.gemspec +37 -0
 - metadata +159 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 7dd6dd5f9bad33c4202a6da557a89a36e836d97a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 90fcf9af2d65ac867c0aaa2c6de0fedd15644b6f
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 5250ee091d440fd8b308949b7d40f10e1c3e4cbb862924c5063d7e91238ce45d209c2b213b9f4f2e875e1ed10ffd396da3b97d5bf80b1a4315c9668475c6739b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 46ad2e8d03bb125f52883a0fba0ff4dcf66603a5685800415a969138b8fdc860db5c2fe12ed86592ebda1338e6f44304dc6a19443da537040729bd445750557f
         
     | 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            *.gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            *.rbc
         
     | 
| 
      
 3 
     | 
    
         
            +
            .bundle
         
     | 
| 
      
 4 
     | 
    
         
            +
            .config
         
     | 
| 
      
 5 
     | 
    
         
            +
            .yardoc
         
     | 
| 
      
 6 
     | 
    
         
            +
            .env
         
     | 
| 
      
 7 
     | 
    
         
            +
            .rspec
         
     | 
| 
      
 8 
     | 
    
         
            +
            Gemfile.lock
         
     | 
| 
      
 9 
     | 
    
         
            +
            InstalledFiles
         
     | 
| 
      
 10 
     | 
    
         
            +
            _yardoc
         
     | 
| 
      
 11 
     | 
    
         
            +
            coverage
         
     | 
| 
      
 12 
     | 
    
         
            +
            doc/
         
     | 
| 
      
 13 
     | 
    
         
            +
            lib/bundler/man
         
     | 
| 
      
 14 
     | 
    
         
            +
            pkg
         
     | 
| 
      
 15 
     | 
    
         
            +
            rdoc
         
     | 
| 
      
 16 
     | 
    
         
            +
            spec/reports
         
     | 
| 
      
 17 
     | 
    
         
            +
            test/tmp
         
     | 
| 
      
 18 
     | 
    
         
            +
            test/version_tmp
         
     | 
| 
      
 19 
     | 
    
         
            +
            tmp
         
     | 
| 
      
 20 
     | 
    
         
            +
            *.bundle
         
     | 
| 
      
 21 
     | 
    
         
            +
            *.so
         
     | 
| 
      
 22 
     | 
    
         
            +
            *.o
         
     | 
| 
      
 23 
     | 
    
         
            +
            *.a
         
     | 
| 
      
 24 
     | 
    
         
            +
            mkmf.log
         
     | 
| 
      
 25 
     | 
    
         
            +
            **/.DS_Store
         
     | 
    
        data/.travis.yml
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    | 
         
            File without changes
         
     | 
    
        data/CONTRIBUTORS.md
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            * Andrey Pronin <moonfly.msk@gmail.com> aka moonfly (https://github.com/moonfly)
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.md
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2014 [CONTRIBUTORS.md](https://github.com/moonfly/store_complex/master/CONTRIBUTORS.md)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 6 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 7 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 8 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 9 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 10 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 14 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 19 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 20 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 21 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 22 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,178 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # StoreComplex
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Stores complex data that includes Arrays and Hashes (possibly nested) in an attribute inside hstore field. The most typical usage scenario is storing arrays in hstore, but it can handle more complex cases. 
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            [](https://travis-ci.org/moonfly/store_complex)
         
     | 
| 
      
 6 
     | 
    
         
            +
            [](https://coveralls.io/r/moonfly/store_complex?branch=master)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                gem 'store_complex'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                $ gem install store_complex
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            ### Reminder: What Rails already has
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            ActiveRecord in Rails 4 already provides methods for dealing with individual attributes inside [PostgresSQL hstore and json](http://www.postgresql.org/docs/9.3/static/hstore.html) fields.
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            Let's consider an example. There is a database table (and a corresponding ActiveRecord model) that describes some blog authors.
         
     | 
| 
      
 29 
     | 
    
         
            +
            Among other data, it has an hstore field called `properties` that captures various optional bits of information about an author: 
         
     | 
| 
      
 30 
     | 
    
         
            +
            email, facebook account, personal blog address, etc.
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            In Rails 4 you can get convenient access to the individual attributes inside `properties` using [`store_accessor`](http://api.rubyonrails.org/classes/ActiveRecord/Store.html):
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 35 
     | 
    
         
            +
            class Author < ActiveRecord::Base
         
     | 
| 
      
 36 
     | 
    
         
            +
              store_accessor :properties, :email, :facebook, :blog
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            author = Author.new(name:'Uber Guru')
         
     | 
| 
      
 40 
     | 
    
         
            +
            author.properties                       # => nil
         
     | 
| 
      
 41 
     | 
    
         
            +
            author.email = 'somebody@example.org'   # will store this email in properties
         
     | 
| 
      
 42 
     | 
    
         
            +
            author.properties                       # => {"email"=>"somebody@example.org"}
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            author.save!
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            author = Author.find_by_name('Uber Guru')
         
     | 
| 
      
 47 
     | 
    
         
            +
            author.properties                       # => {"email"=>"somebody@example.org"}
         
     | 
| 
      
 48 
     | 
    
         
            +
            author.email                            # => 'somebody@example.org'
         
     | 
| 
      
 49 
     | 
    
         
            +
            ```
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            But what if we want to let tha authors specify more than a single email. OK, simple, the `email` property will now be an array. Not, so fast...
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 54 
     | 
    
         
            +
            author = Author.new(name:'Uber Guru')
         
     | 
| 
      
 55 
     | 
    
         
            +
            author.properties                       # => nil
         
     | 
| 
      
 56 
     | 
    
         
            +
            author.email = ['somebody@example.org','somebody@example.com']
         
     | 
| 
      
 57 
     | 
    
         
            +
            author.properties                       # => {"email"=>["somebody@example.org", "somebody@example.com"]} 
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            author.save!
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            author = Author.find_by_name('Uber Guru')
         
     | 
| 
      
 62 
     | 
    
         
            +
            author.properties                       # => {"email"=>"[\"somebody@example.org\", \"somebody@example.com\"]"}
         
     | 
| 
      
 63 
     | 
    
         
            +
            author.email                            # => "[\"somebody@example.org\", \"somebody@example.com\"]"
         
     | 
| 
      
 64 
     | 
    
         
            +
            # Oh-oh! :(
         
     | 
| 
      
 65 
     | 
    
         
            +
            ```
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            And instead of an array we got back a string representation of that array.
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            So, can we do something about it? Yes, meet `store_complex`...
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            ### How to use `store_complex`
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            In your model, use `store_complex` in place of `store_accessor`. That's it!
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 76 
     | 
    
         
            +
            class Author < ActiveRecord::Base
         
     | 
| 
      
 77 
     | 
    
         
            +
              store_complex :properties, :email
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            author = Author.new(name:'Uber Guru')
         
     | 
| 
      
 81 
     | 
    
         
            +
            author.properties                       # => nil
         
     | 
| 
      
 82 
     | 
    
         
            +
            author.email = ['somebody@example.org','somebody@example.com']
         
     | 
| 
      
 83 
     | 
    
         
            +
            author.properties                       # => {"email"=>["somebody@example.org", "somebody@example.com"]} 
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            author.save!
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            author = Author.find_by_name('Uber Guru')
         
     | 
| 
      
 88 
     | 
    
         
            +
            author.properties                       # => {"email"=>"[\"somebody@example.org\", \"somebody@example.com\"]"}
         
     | 
| 
      
 89 
     | 
    
         
            +
            author.email                            # => ["somebody@example.org","somebody@example.com"]
         
     | 
| 
      
 90 
     | 
    
         
            +
            # Success! :)
         
     | 
| 
      
 91 
     | 
    
         
            +
            ```
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
            ### What `store_complex` does
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
            `store_complex` allows to store arrays and hashes in hstore attributes. Those arrays and hashes can contain as their values or keys (for hashes):
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
            - strings, numbers, booleans, nils - will be stored 'as is';
         
     | 
| 
      
 99 
     | 
    
         
            +
            - other arrays and hashes - yes, nesting is possible;
         
     | 
| 
      
 100 
     | 
    
         
            +
            - symbols - will be converted to strings;
         
     | 
| 
      
 101 
     | 
    
         
            +
            - other data types if they can be converted to strings using `String(value)` - and yes, they **will** be converted to strings.
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            One important note: If you store something but array or hash, it will be wrapped into an array. `store_complex` is not for simple data types, use 'store_accessor' for that. The only exception is `nil`, which deletes the attribute from hstore. And if there is no attribute in hstore, the `store_complex` accessor will return an empty array: `[]`.
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            Example:
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 108 
     | 
    
         
            +
            class Author < ActiveRecord::Base
         
     | 
| 
      
 109 
     | 
    
         
            +
              store_complex :properties, :email
         
     | 
| 
      
 110 
     | 
    
         
            +
            end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            author = Author.new(name:'Uber Guru')
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            author.properties                       # => nil
         
     | 
| 
      
 115 
     | 
    
         
            +
            author.email                            # => []
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            author.email = 'somebody@example.org'   #
         
     | 
| 
      
 118 
     | 
    
         
            +
            author.email                            # => ["somebody@example.org"]
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            author.email = nil                      #
         
     | 
| 
      
 121 
     | 
    
         
            +
            author.email                            # => []
         
     | 
| 
      
 122 
     | 
    
         
            +
            ```
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            Another awesome feature of `store_complex` is that it tracks not only assignments to the "complex" attribute, but also all operations on the hash or array (inlcuding those nested within!) that change the object (all those `sort!` and `delete` calls). Thanks to [observable_object gem](https://github.com/moonfly/observable_object) (and me as its author ;-) ) for that awesome behavior. 
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            To get you excited, here is an example below:
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 129 
     | 
    
         
            +
            class Author < ActiveRecord::Base
         
     | 
| 
      
 130 
     | 
    
         
            +
              store_complex :properties, :email
         
     | 
| 
      
 131 
     | 
    
         
            +
            end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            author = Author.new(name:'Uber Guru')
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            author.properties                             # => nil
         
     | 
| 
      
 136 
     | 
    
         
            +
            author.email                                  # => []
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            author.email = { 
         
     | 
| 
      
 139 
     | 
    
         
            +
              "somebody@example.org" => "personal", 
         
     | 
| 
      
 140 
     | 
    
         
            +
              "somebody@example.com" => "work", 
         
     | 
| 
      
 141 
     | 
    
         
            +
              "somebody@business.nowhere" => "work"
         
     | 
| 
      
 142 
     | 
    
         
            +
            }
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            author.email.delete_if { |k,v| v == 'work' }  # delete all work emails
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            author.save!
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            author = Author.find_by_name('Uber Guru')
         
     | 
| 
      
 149 
     | 
    
         
            +
            author.email                                  # => {"somebody@example.org"=>"personal"} 
         
     | 
| 
      
 150 
     | 
    
         
            +
            # Perfect!
         
     | 
| 
      
 151 
     | 
    
         
            +
            ```
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
            ## Versioning
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
            Semantic versioning (http://semver.org/spec/v2.0.0.html) is used. 
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            For a version number MAJOR.MINOR.PATCH, unless MAJOR is 0:
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
            1. MAJOR version is incremented when incompatible API changes are made,
         
     | 
| 
      
 160 
     | 
    
         
            +
            2. MINOR version is incremented when functionality is added in a backwards-compatible manner, 
         
     | 
| 
      
 161 
     | 
    
         
            +
            3. PATCH version is incremented when backwards-compatible bug fixes are made.
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            Major version "zero" (0.y.z) is for initial development. Anything may change at any time. 
         
     | 
| 
      
 164 
     | 
    
         
            +
            The public API should not be considered stable. 
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
            ## Dependencies
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
            - Ruby >= 2.1
         
     | 
| 
      
 169 
     | 
    
         
            +
            - Rails >= 4.0
         
     | 
| 
      
 170 
     | 
    
         
            +
            - observable_object
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
            1. Fork it ( https://github.com/moonfly/store_complex/fork )
         
     | 
| 
      
 175 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 176 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 177 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 178 
     | 
    
         
            +
            5. Create a new Pull Request
         
     | 
    
        data/Rakefile
    ADDED
    
    
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'store_complex/version'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'observable_object'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module StoreComplex
         
     | 
| 
      
 6 
     | 
    
         
            +
              def self.obj_to_store(value)
         
     | 
| 
      
 7 
     | 
    
         
            +
                return nil if value.nil?
         
     | 
| 
      
 8 
     | 
    
         
            +
                JSON.generate(value.is_a?(Hash) ? value : Array(value))
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              def self.store_to_obj(value)
         
     | 
| 
      
 11 
     | 
    
         
            +
                return [] if value.nil?
         
     | 
| 
      
 12 
     | 
    
         
            +
                JSON.parse(value)
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              module Accessor
         
     | 
| 
      
 16 
     | 
    
         
            +
                def store_complex(store_name,*attr_names)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  attr_names.each do |name|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    attr_set = name.to_s+'='
         
     | 
| 
      
 19 
     | 
    
         
            +
                    
         
     | 
| 
      
 20 
     | 
    
         
            +
                    define_method(name) do
         
     | 
| 
      
 21 
     | 
    
         
            +
                      value = (self.send(store_name) || {})[name.to_s]
         
     | 
| 
      
 22 
     | 
    
         
            +
                      ObservableObject::deep_wrap( StoreComplex::store_to_obj(value) ) { |obj| self.send(attr_set, obj) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    
         
     | 
| 
      
 25 
     | 
    
         
            +
                    define_method(attr_set) do |value|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      store = self.send(store_name) || {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                      store[name.to_s] = StoreComplex::obj_to_store(value)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      self.send(store_name.to_s+'=',store)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ActiveRecord.extend StoreComplex::Accessor
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'store_complex/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = 'store_complex'
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = StoreComplex::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ['moonfly (Andrey Pronin)']
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ['moonfly.msk@gmail.com']
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.summary       = %q{Store complex data (arrays, hashes) in hstore attributes}
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.description   = <<-EOF
         
     | 
| 
      
 13 
     | 
    
         
            +
              Stores complex data that includes Arrays and Hashes (possibly nested) in an attribute inside hstore field. 
         
     | 
| 
      
 14 
     | 
    
         
            +
              The most typical usage scenario is storing arrays in hstore, but it can handle more complex cases.
         
     | 
| 
      
 15 
     | 
    
         
            +
              EOF
         
     | 
| 
      
 16 
     | 
    
         
            +
              spec.homepage      = 'https://github.com/moonfly/store_complex'
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.license       = 'MIT'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              spec.files         = `git ls-files -z`.split("\x0")
         
     | 
| 
      
 20 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
      
 21 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.require_paths = ['lib']
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.rdoc_options = ['--charset=UTF-8']
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.extra_rdoc_files = %w[README.md CONTRIBUTORS.md LICENSE.md]
         
     | 
| 
      
 26 
     | 
    
         
            +
              
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.required_ruby_version = '>= 2.1.0'
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_dependency 'rails', '>= 4.0'
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_dependency 'observable_object'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              spec.add_development_dependency 'bundler', '>= 1.6'
         
     | 
| 
      
 33 
     | 
    
         
            +
              spec.add_development_dependency 'rake'
         
     | 
| 
      
 34 
     | 
    
         
            +
              spec.add_development_dependency 'rspec', '~> 3.0'
         
     | 
| 
      
 35 
     | 
    
         
            +
              spec.add_development_dependency 'coveralls'
         
     | 
| 
      
 36 
     | 
    
         
            +
              spec.add_development_dependency 'dotenv'
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,159 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: store_complex
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - moonfly (Andrey Pronin)
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-10-12 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: rails
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '4.0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '4.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: observable_object
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '1.6'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '1.6'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 83 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 84 
     | 
    
         
            +
              name: coveralls
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 97 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 98 
     | 
    
         
            +
              name: dotenv
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 100 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 101 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 102 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 103 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 104 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 105 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 106 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 107 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 108 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 109 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 110 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 111 
     | 
    
         
            +
            description: "  Stores complex data that includes Arrays and Hashes (possibly nested)
         
     | 
| 
      
 112 
     | 
    
         
            +
              in an attribute inside hstore field. \n  The most typical usage scenario is storing
         
     | 
| 
      
 113 
     | 
    
         
            +
              arrays in hstore, but it can handle more complex cases.\n"
         
     | 
| 
      
 114 
     | 
    
         
            +
            email:
         
     | 
| 
      
 115 
     | 
    
         
            +
            - moonfly.msk@gmail.com
         
     | 
| 
      
 116 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 117 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 118 
     | 
    
         
            +
            extra_rdoc_files:
         
     | 
| 
      
 119 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 120 
     | 
    
         
            +
            - CONTRIBUTORS.md
         
     | 
| 
      
 121 
     | 
    
         
            +
            - LICENSE.md
         
     | 
| 
      
 122 
     | 
    
         
            +
            files:
         
     | 
| 
      
 123 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 124 
     | 
    
         
            +
            - ".travis.yml"
         
     | 
| 
      
 125 
     | 
    
         
            +
            - CHANGELOG.md
         
     | 
| 
      
 126 
     | 
    
         
            +
            - CONTRIBUTORS.md
         
     | 
| 
      
 127 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 128 
     | 
    
         
            +
            - LICENSE.md
         
     | 
| 
      
 129 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 130 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 131 
     | 
    
         
            +
            - lib/store_complex.rb
         
     | 
| 
      
 132 
     | 
    
         
            +
            - lib/store_complex/version.rb
         
     | 
| 
      
 133 
     | 
    
         
            +
            - store_complex.gemspec
         
     | 
| 
      
 134 
     | 
    
         
            +
            homepage: https://github.com/moonfly/store_complex
         
     | 
| 
      
 135 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 136 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 137 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 138 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 139 
     | 
    
         
            +
            rdoc_options:
         
     | 
| 
      
 140 
     | 
    
         
            +
            - "--charset=UTF-8"
         
     | 
| 
      
 141 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 142 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 143 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 144 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 145 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 146 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 147 
     | 
    
         
            +
                  version: 2.1.0
         
     | 
| 
      
 148 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 149 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 150 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 151 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 152 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 153 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 154 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 155 
     | 
    
         
            +
            rubygems_version: 2.2.2
         
     | 
| 
      
 156 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 157 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 158 
     | 
    
         
            +
            summary: Store complex data (arrays, hashes) in hstore attributes
         
     | 
| 
      
 159 
     | 
    
         
            +
            test_files: []
         
     |