senotrusov-ruby-xml-mapper 1.0.3 → 1.0.4

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.
@@ -12,13 +12,21 @@
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
-
16
15
 
17
- # TODO Эта библиотека требует рефакторинга. Стоит выделить маппинг в отдельные объекты, а не держать всё размазанным по исходному классу. Опять же, это сделает проще обратный маппинг - из объектов в XML
16
+
17
+ # In fact, this is prototype to define requirements.
18
+ # TODO: refactoring
19
+ # TODO: Extract mapping to separate object
20
+ # TODO: More clear caching
21
+ # TODO: File loading with filesystem restrictions and current directory (based on parent xml directory)
22
+ # TODO: Use more libxml API
18
23
 
19
24
  require 'libxml'
20
25
 
21
26
  module RubyXmlMapper
27
+ mattr_accessor :file_cache
28
+ self.file_cache = {}
29
+
22
30
  def self.included model
23
31
  model.extend RubyXmlMapper::RubyXmlMapperClassMethods
24
32
 
@@ -34,22 +42,11 @@ module RubyXmlMapper
34
42
  model.xml_child_mappings = {}
35
43
  end
36
44
 
37
- # Source loading is ugly
38
- def initialize_from_xml node, load_source = true
45
+ def initialize_from_xml node
39
46
  initialize_from_xml_attr_mapping(node) if xml_attr_mappings.length
40
-
41
- # TODO must not be a magic attribute
42
- if @source && load_source
43
- unless source_dir_path
44
- raise "source_dir_path not defined in #{self.class.inspect}"
45
- end
46
-
47
- initialize_from_xml(self.class.parse_xml_file(File.expand_path_restricted(@source, source_dir_path)), false)
48
- else
49
- initialize_from_xml_child_mapping(node) if xml_child_mappings.length
50
- initialize_from_xml_self_mapping(node) if xml_self_mapping
51
- initialize_from_xml_content_mapping(node) if xml_content_mapping
52
- end
47
+ initialize_from_xml_child_mapping(node) if xml_child_mappings.length
48
+ initialize_from_xml_self_mapping(node) if xml_self_mapping
49
+ initialize_from_xml_content_mapping(node) if xml_content_mapping
53
50
  end
54
51
 
55
52
  private
@@ -157,13 +154,21 @@ module RubyXmlMapper
157
154
  end
158
155
 
159
156
  def new_from_xml_file file_name
160
- new_from_xml_node(parse_xml_file(file_name))
157
+ RubyXmlMapper.file_cache[file_name] ||= new_from_xml_node(parse_xml_file(file_name))
161
158
  end
162
159
 
163
160
  def new_from_xml_node node
164
- allocated = allocate
165
- allocated.initialize_from_xml node
166
- allocated
161
+ if node.attributes["source"]
162
+ unless source_dir_path
163
+ raise "source_dir_path not defined in #{self.class.inspect}"
164
+ end
165
+ new_from_xml_file(File.expand_path_restricted(node.attributes["source"], source_dir_path))
166
+ else
167
+ allocated = allocate
168
+ allocated.initialize_from_xml node
169
+ allocated.after_initialize if allocated.respond_to?(:after_initialize)
170
+ allocated
171
+ end
167
172
  end
168
173
 
169
174
  def xml args
@@ -207,10 +212,10 @@ module RubyXmlMapper
207
212
  def register_self_mapping args
208
213
  if args[:type].kind_of?(Array)
209
214
  register_type_array(args)
210
- elsif args[:type] == :self && self < RubyXmlMapper::HashOfStringAndNumeric
215
+ elsif args[:type] == :self && self < RubyXmlMapper::Hash
211
216
 
212
217
  else
213
- raise(":type must be kind_of Array or :self with the following supported types: RubyXmlMapper::HashOfStringAndNumeric )")
218
+ raise(":type must be kind_of Array or :self with the following supported types: RubyXmlMapper::Hash )")
214
219
  end
215
220
 
216
221
  self.xml_self_mapping = args
@@ -14,8 +14,6 @@
14
14
  # limitations under the License.
15
15
 
16
16
 
17
- # TODO: Double check .strip - is it needed actually
18
-
19
17
  class String
20
18
  def self.new_from_xml_attr attr
21
19
  new(attr.value.strip.gsub(/\s*[\r\n]\s*/, "\n"))
@@ -66,22 +64,27 @@ class RubyXmlMapper::Boolean
66
64
  end
67
65
  end
68
66
 
69
- class RubyXmlMapper::HashOfStringAndNumeric < Hash
70
- def self.new_from_xml_node node
71
- created = new
72
- created.initialize_from_xml_node node
73
- created
74
- end
67
+ class RubyXmlMapper::Hash < Hash
75
68
 
76
69
  def initialize_from_xml_node node
77
70
  node.each_element do |child|
78
- self[child.name.to_sym] = autocast_value(child.content)
71
+ next if xml_child_mappings.has_key?(child.name)
72
+
73
+ self[child.name.to_sym] = if child.attributes["type"] && respond_to?(cast_method = "cast_to_#{child.attributes["type"]}")
74
+ __send__(cast_method, child.content)
75
+ else
76
+ autocast_value(child.content)
77
+ end
79
78
  end
79
+
80
80
  node.each_attr do |attr|
81
+ next if xml_attr_mappings.has_key?(attr.name)
82
+
81
83
  self[attr.name.to_sym] = autocast_value(attr.value)
82
84
  end
83
85
  end
84
86
 
87
+ # we're eating copypasta!
85
88
  def autocast_value value
86
89
  if value =~ /\A\s*-*\d+\.\d+\s*\z/
87
90
  value.to_f
@@ -103,6 +106,33 @@ class RubyXmlMapper::HashOfStringAndNumeric < Hash
103
106
 
104
107
  end
105
108
  end
109
+
110
+ def cast_to_float value
111
+ value.to_f
112
+ end
113
+
114
+ def cast_to_integer value
115
+ value.to_i
116
+ end
117
+
118
+ def cast_to_range value
119
+ matchdata = value.match(/\A\s*(-*\d+)\s*\.\.\s*(-*\d+)\s*\z/)
120
+ Range.new(matchdata[1].to_i, matchdata[2].to_i)
121
+ end
122
+
123
+ def cast_to_boolean value
124
+ if value =~ /\A\s*true\s*\z/i
125
+ true
126
+ elsif value =~ /\A\s*false\s*\z/i
127
+ false
128
+ else
129
+ nil
130
+ end
131
+ end
132
+
133
+ def cast_to_string value
134
+ value.strip.gsub(/\s*[\r\n]\s*/, "\n").gsub(/\n\s*\n/, "\n")
135
+ end
106
136
  end
107
137
 
108
138
  require 'time'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: senotrusov-ruby-xml-mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanislav Senotrusov
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-27 00:00:00 -07:00
12
+ date: 2009-07-30 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,6 +22,16 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 1.1.3
24
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rails
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
25
35
  description:
26
36
  email: senotrusov@gmail.com
27
37
  executables: []