diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce3c397 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +test/tmp +*.gem diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e004563 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 Cody Caughlan. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.[ \ No newline at end of file diff --git a/README b/README index f5cc5ca..86b0d52 100644 --- a/README +++ b/README @@ -1 +1,3 @@ -Enable Postgres HStore column serialization for your ActiveRecord / Rails 3.1+ project +Enable Postgres HStore column serialization for your ActiveRecord / Rails 3.1+ project. + +Huge thanks and credit to https://github.com/softa/activerecord-postgres-hstore for code and inspiration. diff --git a/active_record_hstore_serializer.gemspec b/active_record_hstore_serializer.gemspec new file mode 100644 index 0000000..1e60e3e --- /dev/null +++ b/active_record_hstore_serializer.gemspec @@ -0,0 +1,23 @@ +Gem::Specification.new do |s| + s.name = 'active_record_hstore_serializer' + s.version = '0.0.2' + s.date = '2011-11-19' + s.summary = "Serialize attributes using HStore in ActiveRecord / Rails 3.1+" + s.description = "Leverage Postgres HStore for awesome attribute serialization." + s.authors = ["Cody Caughlan"] + s.email = 'toolbag@gmail.com' + s.files = ["lib/active_record_hstore_serializer.rb"] + s.homepage = 'https://github.com/ruckus/active_record_hstore_serializer' + s.files = [ + ".gitignore", + "LICENSE", + "README", + "lib/active_record_hstore_serializer.rb", + "lib/active_record_hstore_serializer/hash.rb", + "lib/active_record_hstore_serializer/string.rb", + "lib/active_record_hstore_serializer/hstore_serializer.rb", + "active_record_hstore_serializer.gemspec" + ] + s.require_paths = ['lib'] + s.has_rdoc = false +end \ No newline at end of file diff --git a/lib/active_record_hstore_serializer.rb b/lib/active_record_hstore_serializer.rb new file mode 100644 index 0000000..88722e3 --- /dev/null +++ b/lib/active_record_hstore_serializer.rb @@ -0,0 +1,3 @@ +require 'active_record_hstore_serializer/hash' +require 'active_record_hstore_serializer/string' +require 'active_record_hstore_serializer/hstore_serializer' \ No newline at end of file diff --git a/lib/active_record_hstore_serializer/hash.rb b/lib/active_record_hstore_serializer/hash.rb new file mode 100644 index 0000000..8539930 --- /dev/null +++ b/lib/active_record_hstore_serializer/hash.rb @@ -0,0 +1,13 @@ +class Hash + + def to_hstore + return "" if empty? + map {|idx, val| %Q{"#{idx.to_s}"=>"#{val.to_s}"} }.join(', ') + end + + # If the method from_hstore is called in a Hash, it just returns self. + def from_hstore + self + end + +end \ No newline at end of file diff --git a/lib/active_record_hstore_serializer/hstore_serializer.rb b/lib/active_record_hstore_serializer/hstore_serializer.rb new file mode 100644 index 0000000..1d43715 --- /dev/null +++ b/lib/active_record_hstore_serializer/hstore_serializer.rb @@ -0,0 +1,15 @@ +class HstoreSerializer + + def self.load(text) + return unless text + text.from_hstore + end + + def self.dump(text) + text.to_hstore + end +end + + + + diff --git a/lib/active_record_hstore_serializer/string.rb b/lib/active_record_hstore_serializer/string.rb new file mode 100644 index 0000000..3ae6566 --- /dev/null +++ b/lib/active_record_hstore_serializer/string.rb @@ -0,0 +1,35 @@ +class String + + # If the value os a column is already a String and it calls to_hstore, it + # just returns self. Validation occurs afterwards. + def to_hstore + self + end + + # Validates the hstore format. Valid formats are: + # * An empty string + # * A string like %("foo"=>"bar"). I'll call it a "double quoted hstore format". + # * A string like %('foo'=>'bar'). I'll call it a "single quoted hstore format". + def valid_hstore? + return true if empty? || self == "''" + # This is what comes from the database + dbl_quotes_re = /"([^"]+)"=>"([^"]+)"/ + # TODO + # This is what comes from the plugin + # this is a big problem, 'cause regexes does not know how to count... + # how should i very values quoted with two single quotes? using .+ sux. + sngl_quotes_re = /'(.+)'=>'(.+)'/ + self.match(dbl_quotes_re) || self.match(sngl_quotes_re) + end + + # Creates a hash from a valid double quoted hstore format, 'cause this is the format + # that postgresql spits out. + def from_hstore + Hash[ scan(/"([^"]+)"=>"([^"]+)"/) ] + end + + def escape_quotes + self.gsub(/'/,"''") + end + +end \ No newline at end of file