pg-xml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7fafbeb6bb53498ffc42dd1efe5d683c451a28c
4
+ data.tar.gz: cf61d5ecfe41b83d6835cd251152b2551403747a
5
+ SHA512:
6
+ metadata.gz: de4899da7e8003a8b68fdad57419f9d8a2049ba5c579bc270aa0447570db23c4741d2618637970959ef7aa6c93f26e5afefae83da8d641bed56aec706b01da60
7
+ data.tar.gz: c44359eba77634a371d44f581b652d6a6f0b5772b511327a54251e1bc5887c9e87a25b13a3509a9ae1f3f455286e266b3af1eec1f911f8c245afaf0406140f7f
@@ -0,0 +1,85 @@
1
+ # use, e.g.,
2
+ # has_xml_column :properties
3
+ # in your ActiveRecord model
4
+
5
+ # in a migration, use e.g.
6
+ # add_xpath_index :users, :properties, '/xml/first_name'
7
+ # to index into the XML
8
+
9
+ module ActiveRecord
10
+
11
+ class Base
12
+
13
+ # define the has_xml_column :col_name name
14
+ def self.has_xml_column attr_name
15
+
16
+ # serialize using the custom serializer
17
+ serialize attr_name, ActiveRecord::Coders::XML
18
+ # validate XML before saving
19
+ validate "validate_#{attr_name}_xml"
20
+
21
+ # define the attribute writer to accept a string
22
+ # and convert it to XML
23
+ define_method("#{attr_name}=") do |val|
24
+ if val.is_a? String
25
+ val = PgXML.load(val)
26
+ end
27
+ self[attr_name] = val
28
+ end
29
+
30
+ # validate XML before writing to database
31
+ define_method("validate_#{attr_name}_xml") do
32
+ # TODO make this work with hpricot
33
+ return true if self[attr_name].nil? || self[attr_name].errors == []
34
+ self[attr_name].errors.each do |e|
35
+ errors.add(attr_name, e.to_s)
36
+ end
37
+ return false
38
+ end
39
+
40
+ end
41
+ end
42
+
43
+ # support the add_xpath_index and make it reversible
44
+ module ConnectionAdapters
45
+ module SchemaStatements
46
+
47
+ # enable adding an xpath index
48
+ def add_xpath_index table_name, column_name, path, index_name=nil
49
+ # generate an index name
50
+ index_name ||= "index_#{table_name}_on_#{column_name}__#{path}"
51
+ index_name = index_name.downcase.gsub(/[^a-z0-9]/, '_')
52
+
53
+ # create the index
54
+ execute "CREATE INDEX #{index_name} ON #{table_name}(xpath('#{path}',#{column_name}))"
55
+ end
56
+
57
+
58
+ # can call in any of the following ways
59
+ # remove_xpath_index :users, :properties, '/xml/name'
60
+ # remove_xpath_index :index_users_on_properties__xml_name
61
+ # remove_xpath_index :users, :properties, '/xml/name', :index_users_on_properties__xml_name
62
+ def remove_xpath_index index_name_or_table_name, column_name=nil, path=nil, index_name=nil
63
+ # figure out which version was called
64
+ index_name = index_name_or_table_name if !column_name
65
+
66
+ # transform index name
67
+ index_name ||= "index_#{table_name}_on_#{column_name}__#{path}"
68
+ index_name = index_name.downcase.gsub(/[^a-z0-9]/, '_')
69
+
70
+ # drop the index
71
+ execute "DROP INDEX #{index_name}"
72
+ end
73
+
74
+ # TODO this doesn't get called -- why?
75
+ # adding the xpath index should be reversible
76
+ def invert_add_xpath_index(args)
77
+ # table_name, column_name, path, index_name = *args
78
+ # [:remove_index, [table_name, column_name, path, index_name]]
79
+ [:remove_xpath_index, args]
80
+ end
81
+
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveRecord
2
+ module Coders
3
+ class XML
4
+
5
+ def self.load(xml_string)
6
+ new(PgXML.default).load(xml_string)
7
+ end
8
+
9
+ def self.dump(xml_document)
10
+ new(PgXML.default).dump(xml_document)
11
+ end
12
+
13
+ def initialize(default=nil)
14
+ @default=default
15
+ end
16
+
17
+ def dump(xml_document)
18
+ (xml_document.nil? && @default.nil?) ? nil : PgXML.dump( xml_document || @default )
19
+ end
20
+
21
+ def load(xml_string)
22
+ xml_string.nil? ? @default : PgXML.load(xml_string)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,38 @@
1
+ # note: none of this is tested against Hpricot
2
+ # the goal was to allow either hpricot or nokogiri, but
3
+ # support for "using either" is half-assed at best
4
+
5
+ module PgXML
6
+
7
+ # complex line of code determining whether we have access to nokogiri or hpricot.
8
+ XML_PARSER_TYPE = ( require('nokogiri') || true rescue # evaluates to true if we have nokogiri
9
+ require('hpricot') && false rescue # evaluates to valse if we have hpricot
10
+ raise LoadError, "Either nokogiri or hpricot is required" # raises an error if we have neither
11
+ ) ? :nokogiri : :hpricot
12
+
13
+ # get which XML parser we are using
14
+ def self.parser_type
15
+ XML_PARSER_TYPE
16
+ end
17
+
18
+ def self.load xml_str
19
+ parse xml_str
20
+ end
21
+
22
+ def self.dump xml_document
23
+ xml_document.to_s
24
+ end
25
+
26
+ # Valid xml requires a root node.
27
+ def self.default
28
+ parse '<xml></xml>'
29
+ end
30
+
31
+ # use our parser to create an XML document
32
+ # warning: nokogiri is friendly -- if you feed it invalid XML it will fail silently
33
+ # Nokogiri::XML.parse('<xml><xml>').to_s ~> <xml><xml/></xml>
34
+ def self.parse xml_str
35
+ XML_PARSER_TYPE == :nokogiri ? Nokogiri::XML.parse(xml_str) : Hpricot(xml_str)
36
+ end
37
+
38
+ end
data/lib/pg-xml.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'active_support'
2
+
3
+ # ActiveSupport.on_load :active_record do
4
+ require "pg-xml/pg_xml"
5
+ require "pg-xml/coder"
6
+ require "pg-xml/activerecord"
7
+ # end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pg-xml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kai Stinchcombe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: postgresql xml datatype support for activerecord -- heavily based on
28
+ pg-hstore and activerecord-postgres-hstore
29
+ email:
30
+ - k@i.stinchcom.be
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - lib/pg-xml.rb
36
+ - lib/pg-xml/activerecord.rb
37
+ - lib/pg-xml/coder.rb
38
+ - lib/pg-xml/pg_xml.rb
39
+ homepage:
40
+ licenses: []
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ - lib/pg-xml
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.0.3
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: postgresql xml datatype support for activerecord -- heavily based on pg-hstore
63
+ and activerecord-postgres-hstore
64
+ test_files: []