pg-xml 0.0.1
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/lib/pg-xml/activerecord.rb +85 -0
- data/lib/pg-xml/coder.rb +28 -0
- data/lib/pg-xml/pg_xml.rb +38 -0
- data/lib/pg-xml.rb +7 -0
- metadata +64 -0
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
|
data/lib/pg-xml/coder.rb
ADDED
|
@@ -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
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: []
|