openxml-package 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4897a42b3b6601e4c9592fd0a0dfb280d00924bc
4
- data.tar.gz: e897af932351b707af9c4b954eb64437dcb85db3
3
+ metadata.gz: 1a0436dc9e0622316c63a9a049ebe243ebe50bd0
4
+ data.tar.gz: f598315aff5dea761320ef51fe2f64709bba9073
5
5
  SHA512:
6
- metadata.gz: 8ef6f7fd79923969da139af148dcb8ee285216d7794a24ee5d6e74602a9ac6ba7fe05f95bdef3b6ac877fd59900210f3742f9658296c2e40f53909c40839238c
7
- data.tar.gz: 94c22130fd32fca51a16ed4714534aa141a84c4a89e1399723ce4867b736cb3d440e9e134e045c21f663d3071df368483f233879540e267c335e150974d4573b
6
+ metadata.gz: c19ae66a76c4abcd5a4c431e567a0cf55060e35827afba22c2ba27bc35d9f7d1773c009e55b9e3a48d61221aca7c3811ec2a9907f6517432d7df7eebdcbd21ed
7
+ data.tar.gz: 2c17f6398cd89b909e36e8d3dd6d42a5f761ae7df2da319cf5ca99b609eb17a6c9e82dab5496cc13a5521dfc0e745a0ea2365589494ece87820fa919a7eed6d3
@@ -1,3 +1,3 @@
1
1
  module OpenXmlPackage
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -13,11 +13,16 @@ module OpenXml
13
13
  module InstanceMethods
14
14
 
15
15
  def property_xml(xml)
16
+ ensure_required_choices
16
17
  props = active_properties
17
18
  return unless render_properties? props
18
19
  props.each { |prop| prop.to_xml(xml) }
19
20
  end
20
21
 
22
+ def properties_attributes
23
+ {}
24
+ end
25
+
21
26
  end
22
27
 
23
28
  end
@@ -1,3 +1,5 @@
1
+ require "openxml/unmet_requirement"
2
+
1
3
  module OpenXml
2
4
  module HasAttributes
3
5
 
@@ -7,10 +9,12 @@ module OpenXml
7
9
 
8
10
  module ClassMethods
9
11
 
10
- def attribute(name, expects: nil, one_of: nil, in_range: nil, displays_as: nil, namespace: nil, matches: nil, validation: nil, deprecated: false)
12
+ def attribute(name, expects: nil, one_of: nil, in_range: nil, displays_as: nil, namespace: nil, matches: nil, validation: nil, required: false, deprecated: false)
11
13
  bad_names = %w{ tag name namespace properties_tag }
12
14
  raise ArgumentError if bad_names.member? name.to_s
13
15
 
16
+ required_attributes.push(name) if required
17
+
14
18
  attr_reader name
15
19
 
16
20
  define_method "#{name}=" do |value|
@@ -27,17 +31,21 @@ module OpenXml
27
31
  end
28
32
 
29
33
  def attributes
30
- @attributes ||= begin
34
+ @attributes ||= {}.tap do |attrs|
31
35
  if superclass.respond_to?(:attributes)
32
- Hash[superclass.attributes.map { |name, attribute|
33
- [ name, attribute.dup ]
34
- }]
35
- else
36
- {}
36
+ superclass.attributes.each do |key, value|
37
+ attrs[key] = value.dup
38
+ end
37
39
  end
38
40
  end
39
41
  end
40
42
 
43
+ def required_attributes
44
+ @required_attributes ||= [].tap do |attrs|
45
+ attrs.push(*superclass.required_attributes) if superclass.respond_to?(:required_attributes)
46
+ end
47
+ end
48
+
41
49
  def with_namespace(namespace, &block)
42
50
  @attribute_namespace = namespace
43
51
  instance_eval(&block)
@@ -57,9 +65,14 @@ module OpenXml
57
65
  self.class.attributes
58
66
  end
59
67
 
68
+ def required_attributes
69
+ self.class.required_attributes
70
+ end
71
+
60
72
  private
61
73
 
62
74
  def xml_attributes
75
+ ensure_required_attributes_set
63
76
  attributes.each_with_object({}) do |(name, options), attrs|
64
77
  display, namespace = options
65
78
  value = send(name)
@@ -69,6 +82,14 @@ module OpenXml
69
82
  end
70
83
  end
71
84
 
85
+ def ensure_required_attributes_set
86
+ unset_attributes = required_attributes.reject do |attr|
87
+ instance_variable_defined?("@#{attr}")
88
+ end
89
+ message = "Required attribute(s) #{unset_attributes.join(", ")} have not been set"
90
+ raise OpenXml::UnmetRequirementError, message if unset_attributes.any?
91
+ end
92
+
72
93
  def boolean(value)
73
94
  message = "Invalid #{name}: frame must be true or false"
74
95
  raise ArgumentError, message unless [true, false].member? value
@@ -114,6 +135,11 @@ module OpenXml
114
135
  raise ArgumentError, message if !value.is_a?(String) || value.length.zero?
115
136
  end
116
137
 
138
+ def string_or_blank(value)
139
+ message = "Invalid #{name}: must be a string, even if the string is empty"
140
+ raise ArgumentError, message unless value.is_a?(String)
141
+ end
142
+
117
143
  def in_range?(value, range)
118
144
  message = "Invalid #{name}: must be a number between #{range.begin} and #{range.end}"
119
145
  raise ArgumentError, message unless range.include?(value.to_i)
@@ -1,3 +1,5 @@
1
+ require "openxml/unmet_requirement"
2
+
1
3
  module OpenXml
2
4
  module HasProperties
3
5
 
@@ -14,12 +16,13 @@ module OpenXml
14
16
  @properties_tag ||= nil
15
17
  end
16
18
 
17
- def value_property(name, as: nil, klass: nil)
19
+ def value_property(name, as: nil, klass: nil, required: false, default_value: nil)
18
20
  attr_reader name
19
21
 
20
22
  properties[name] = (as || name).to_s
23
+ required_properties[name] = default_value if required
21
24
  classified_name = properties[name].split("_").map(&:capitalize).join
22
- class_name = klass.name unless klass.nil?
25
+ class_name = klass.to_s unless klass.nil?
23
26
  class_name ||= (to_s.split("::")[0...-2] + ["Properties", classified_name]).join("::")
24
27
 
25
28
  (choice_groups[current_group] ||= []).push(name) unless current_group.nil?
@@ -33,17 +36,18 @@ module OpenXml
33
36
  CODE
34
37
  end
35
38
 
36
- def property(name, as: nil, klass: nil)
39
+ def property(name, as: nil, klass: nil, required: false)
37
40
  properties[name] = (as || name).to_s
41
+ required_properties[name] = true if required
38
42
  classified_name = properties[name].split("_").map(&:capitalize).join
39
- class_name = klass.name unless klass.nil?
43
+ class_name = klass.to_s unless klass.nil?
40
44
  class_name ||= (to_s.split("::")[0...-2] + ["Properties", classified_name]).join("::")
41
45
 
42
46
  (choice_groups[current_group] ||= []).push(name) unless current_group.nil?
43
47
 
44
48
  class_eval <<-CODE, __FILE__, __LINE__ + 1
45
49
  def #{name}(*args)
46
- if instance_variable_get("@#{name}").nil?
50
+ unless instance_variable_defined?("@#{name}")
47
51
  group_index = #{@current_group.inspect}
48
52
  ensure_unique_in_group(:#{name}, group_index) unless group_index.nil?
49
53
  instance_variable_set "@#{name}", #{class_name}.new(*args)
@@ -54,8 +58,9 @@ module OpenXml
54
58
  CODE
55
59
  end
56
60
 
57
- def property_choice
61
+ def property_choice(required: false)
58
62
  @current_group = choice_groups.length
63
+ required_choices << @current_group if required
59
64
  yield
60
65
  @current_group = nil
61
66
  end
@@ -65,22 +70,26 @@ module OpenXml
65
70
  end
66
71
 
67
72
  def properties
68
- @properties ||= begin
69
- if superclass.respond_to?(:properties)
70
- Hash[superclass.properties.map { |key, klass_name| [ key, klass_name.dup ] }]
71
- else
72
- {}
73
- end
73
+ @properties ||= {}.tap do |props|
74
+ props.merge!(superclass.properties) if superclass.respond_to?(:properties)
74
75
  end
75
76
  end
76
77
 
77
78
  def choice_groups
78
- @choice_groups ||= begin
79
- if superclass.respond_to?(:choice_groups)
80
- superclass.choice_groups.map(&:dup)
81
- else
82
- []
83
- end
79
+ @choice_groups ||= [].tap do |choices|
80
+ choices.push(*superclass.choice_groups.map(&:dup)) if superclass.respond_to?(:choice_groups)
81
+ end
82
+ end
83
+
84
+ def required_properties
85
+ @required_properties ||= {}.tap do |props|
86
+ props.merge!(superclass.required_properties) if superclass.respond_to?(:required_properties)
87
+ end
88
+ end
89
+
90
+ def required_choices
91
+ @required_choices ||= [].tap do |choices|
92
+ choices.push(*superclass.required_choices) if superclass.respond_to?(:required_choices)
84
93
  end
85
94
  end
86
95
 
@@ -110,6 +119,11 @@ module OpenXml
110
119
 
111
120
  end
112
121
 
122
+ def initialize(*_args)
123
+ super
124
+ build_required_properties
125
+ end
126
+
113
127
  def properties_element
114
128
  @properties_element ||= self.class.properties_element.new
115
129
  end
@@ -131,6 +145,7 @@ module OpenXml
131
145
  end
132
146
 
133
147
  def property_xml(xml)
148
+ ensure_required_choices
134
149
  props = active_properties
135
150
  return unless render_properties? props
136
151
 
@@ -139,6 +154,13 @@ module OpenXml
139
154
  end
140
155
  end
141
156
 
157
+ def build_required_properties
158
+ required_properties.each do |prop, default_value|
159
+ public_send(:"#{prop}=", default_value) if respond_to? :"#{prop}="
160
+ public_send(:"#{prop}")
161
+ end
162
+ end
163
+
142
164
  private
143
165
 
144
166
  def properties
@@ -150,7 +172,9 @@ module OpenXml
150
172
  end
151
173
 
152
174
  def render_properties?(properties=active_properties)
153
- properties.any?(&:render?) || properties_attributes.any?
175
+ properties.any?(&:render?) || properties_attributes.keys.any? do |key|
176
+ properties_element.instance_variable_defined?("@#{key}")
177
+ end
154
178
  end
155
179
 
156
180
  def properties_tag
@@ -165,12 +189,34 @@ module OpenXml
165
189
  self.class.choice_groups
166
190
  end
167
191
 
192
+ def required_properties
193
+ self.class.required_properties
194
+ end
195
+
196
+ def required_choices
197
+ self.class.required_choices
198
+ end
199
+
168
200
  def ensure_unique_in_group(name, group_index)
169
201
  other_names = (choice_groups[group_index] - [name])
170
- unique = other_names.all? { |other_name| !instance_variable_defined?("@#{other_name}") }
202
+ unique = other_names.none? { |other_name| instance_variable_defined?("@#{other_name}") }
171
203
  message = "Property #{name} cannot also be set with #{other_names.join(", ")}."
172
204
  raise ChoiceGroupUniqueError, message unless unique
173
205
  end
174
206
 
207
+ def unmet_choices
208
+ required_choices.reject do |choice_index|
209
+ choice_groups[choice_index].one? do |prop_name|
210
+ instance_variable_defined?("@#{prop_name}")
211
+ end
212
+ end
213
+ end
214
+
215
+ def ensure_required_choices
216
+ unmet_choice_groups = unmet_choices.map { |index| choice_groups[index].join(", ") }
217
+ message = "Required choice from among group(s) (#{unmet_choice_groups.join("), (")}) not made"
218
+ raise OpenXml::UnmetRequirementError, message if unmet_choice_groups.any?
219
+ end
220
+
175
221
  end
176
222
  end
@@ -40,7 +40,7 @@ module OpenXml
40
40
  end
41
41
 
42
42
  def to_xml
43
- build_xml do |xml|
43
+ build_standalone_xml do |xml|
44
44
  xml.Types(xmlns: "http://schemas.openxmlformats.org/package/2006/content-types") {
45
45
  defaults.each { |extension, content_type| xml.Default("Extension" => extension, "ContentType" => content_type) }
46
46
  overrides.each { |part_name, content_type| xml.Override("PartName" => part_name, "ContentType" => content_type) }
@@ -23,7 +23,7 @@ module OpenXml
23
23
  end
24
24
  end
25
25
 
26
- def add_relationship(type, target, id=nil, target_mode=nil)
26
+ def add_relationship(type, target, id=next_id, target_mode=nil)
27
27
  OpenXml::Elements::Relationship.new(type, target, id, target_mode).tap do |relationship|
28
28
  relationships.push relationship
29
29
  end
@@ -56,6 +56,11 @@ module OpenXml
56
56
  private
57
57
  attr_reader :relationships
58
58
 
59
+ def next_id
60
+ @current_id = (@current_id || 0) + 1
61
+ "rId#{@current_id}"
62
+ end
63
+
59
64
  end
60
65
  end
61
66
  end
@@ -0,0 +1,9 @@
1
+ module OpenXml
2
+ module RenderWhenEmpty
3
+
4
+ def render?
5
+ true
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module OpenXml
2
+ class UnmetRequirementError < RuntimeError; end
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openxml-package
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Lail
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-12 00:00:00.000000000 Z
11
+ date: 2017-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -221,8 +221,10 @@ files:
221
221
  - lib/openxml/properties/transparent_container_property.rb
222
222
  - lib/openxml/properties/value_property.rb
223
223
  - lib/openxml/relationship.rb
224
+ - lib/openxml/render_when_empty.rb
224
225
  - lib/openxml/rubyzip_fix.rb
225
226
  - lib/openxml/types.rb
227
+ - lib/openxml/unmet_requirement.rb
226
228
  - openxml-package.gemspec
227
229
  - tmp/.keep
228
230
  homepage: https://github.com/openxml/openxml-package