senotrusov-ruby-xml-mapper 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []