xmlmap 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/xmlmap.rb +111 -0
  3. metadata +58 -0
@@ -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
@@ -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: []