xmlmap 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/xmlmap.rb +111 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 89f1e62b204d268bcbc31b4a3cb33460f529981a
|
4
|
+
data.tar.gz: b3e06527a077456f211c881a8b6db5e3b086a04a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6c4db3bddb27ace3ece6974c493640f8ebcddca815888608ba58c216702a6c34c42d748ffaa85151659eb98780d4825aa9a1e72c4942dbfd1b2a3ff01e7ff44
|
7
|
+
data.tar.gz: f64e3810d0fb97a9fd66e4cb7d858338ce07c519bcc5de3fa4373af7192bcd325525a2e432c94a61e77230b44bf4faecc1f55a03ac84c201cfd66af11fda0f61
|
data/lib/xmlmap.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class String
|
6
|
+
def classify
|
7
|
+
ActiveSupport::Inflector.classify(ActiveSupport::Inflector.singularize(self))
|
8
|
+
end
|
9
|
+
|
10
|
+
def constantize
|
11
|
+
ActiveSupport::Inflector.constantize(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Xmlmap
|
16
|
+
class << self #we stand on the context of the metaclass, the methods here defined wont be instance ones but class methods
|
17
|
+
|
18
|
+
#when Xmlmap is inherited, we create the @xml_map variable in the context of the inheritor metaclass, this variable will contain the results of configuration
|
19
|
+
def inherited(subclass)
|
20
|
+
subclass.class_eval do
|
21
|
+
@xml_map = {}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_url(url)
|
26
|
+
@xml_map[:url] = url
|
27
|
+
@xml_map[:xml_object] = Nokogiri::XML(open(@xml_map[:url]))
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_path(path, opts = {})
|
31
|
+
#if there is an established base we'll build an anonymous function (Proc) that triggers the construction of the route that corresponds to taht base function, else the path for this class will simply be the string in the path parameter. Pay attention to the fact that the xml_path method we call here simpy returns the contents of @xml_map[:path] in the base class. So what we are doing is we are going up the hierarchy until we reeach a "patriarch" class that contains an absolute path and then we add strings for routes as we go down.
|
32
|
+
if opts[:base]
|
33
|
+
@xml_map[:path] = [ Proc.new { opts[:base].to_s.classify.constantize.get_xml_path }, path ]
|
34
|
+
else
|
35
|
+
@xml_map[:path] = path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
#the #all method, which will create an array of fresh instances for all the elements that match the chosen path
|
40
|
+
def all
|
41
|
+
find_many(self.get_xml_path).map do |xml_element|
|
42
|
+
self.new(xml_element)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_xml_path
|
47
|
+
@xml_map[:path]
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_many(path_parts)
|
51
|
+
@xml_map[:xml_object].search stringify_path(path_parts)
|
52
|
+
end
|
53
|
+
|
54
|
+
def stringify_path(path_parts)
|
55
|
+
#if this is a single element, we'll still create an array with a single element just like when we receive an array - we verify in Duck Typing fashion
|
56
|
+
path_parts = [path_parts] unless path_parts.respond_to?(:join)
|
57
|
+
path_parts = path_parts.flatten.map do |path_part|
|
58
|
+
if path_part.respond_to?(:call)
|
59
|
+
path_part.call
|
60
|
+
else
|
61
|
+
path_part
|
62
|
+
end
|
63
|
+
end
|
64
|
+
path_parts.join(' ')
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_destination_relative_path_to_self(destination_name)
|
68
|
+
destination_path = destination_name.classify.constantize.get_xml_path
|
69
|
+
if destination_path.is_a? Array
|
70
|
+
destination_path.last
|
71
|
+
else
|
72
|
+
destination_path
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#lets build a method with the name of the associated entity (yay metaprogramming!), that searches for subelements using the part that is relative to the base (the last) or in the case that the destination entity is not nested into the origin one (that happens when we receive the :non_descendant_path option), calling the ::all method on the associated class. If an anonymous function (Proc) called :conditions is present in options, the found instances will be filtered by it.
|
77
|
+
|
78
|
+
def has_many(what, opts={})
|
79
|
+
define_method(what) do
|
80
|
+
if opts[:non_descendant_path]
|
81
|
+
result_instances = what.to_s.classify.constantize.all
|
82
|
+
else
|
83
|
+
subpath = self.class.get_destination_relative_path_to_self(what.to_s)
|
84
|
+
result_instances = find_many(subpath, what.to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
if opts[:conditions]
|
88
|
+
result_instances = result_instances.select {|result_instance| opts[:conditions].call(self, result_instance) }
|
89
|
+
end
|
90
|
+
result_instances
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
#instance methods
|
96
|
+
|
97
|
+
#this is the method that will run when an inheritor class receives a ::new message
|
98
|
+
def initialize(element)
|
99
|
+
@xml_element = element
|
100
|
+
end
|
101
|
+
|
102
|
+
#we divert all calls to unknown methods of instances of classes that inherit Xmlmap to the associated Nokogiri object for that instance. That way you can use Nokogiri methods like #at, #inner_text, etc directly against the Xmlmap objects
|
103
|
+
def method_missing(name, *args, &block)
|
104
|
+
@xml_element.send(name, *args, &block)
|
105
|
+
end
|
106
|
+
|
107
|
+
#find_many simpy passes the call to the #search Nokogiri method, to bring subelelements by a css string or xpath and creates instances for the corresponding class
|
108
|
+
def find_many(subpath, class_name)
|
109
|
+
self.search(subpath).map {|xml_element| class_name.classify.constantize.new(xml_element) }
|
110
|
+
end
|
111
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xmlmap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maximiliano Guzman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.1
|
27
|
+
description:
|
28
|
+
email: maximiliano.guzman@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/xmlmap.rb
|
34
|
+
homepage: http://rubygems.org/gems/xmlmap
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 2.2.2
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: A simple xml mapping library (uses Nokogiri)
|
58
|
+
test_files: []
|