frodata 0.9.1
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.
- checksums.yaml +7 -0
- data/.autotest +2 -0
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +75 -0
- data/CHANGELOG.md +150 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +427 -0
- data/Rakefile +7 -0
- data/TODO.md +55 -0
- data/frodata.gemspec +34 -0
- data/lib/frodata.rb +36 -0
- data/lib/frodata/entity.rb +332 -0
- data/lib/frodata/entity_container.rb +75 -0
- data/lib/frodata/entity_set.rb +161 -0
- data/lib/frodata/errors.rb +68 -0
- data/lib/frodata/navigation_property.rb +29 -0
- data/lib/frodata/navigation_property/proxy.rb +80 -0
- data/lib/frodata/properties.rb +32 -0
- data/lib/frodata/properties/binary.rb +50 -0
- data/lib/frodata/properties/boolean.rb +37 -0
- data/lib/frodata/properties/collection.rb +50 -0
- data/lib/frodata/properties/complex.rb +114 -0
- data/lib/frodata/properties/date.rb +27 -0
- data/lib/frodata/properties/date_time.rb +83 -0
- data/lib/frodata/properties/date_time_offset.rb +17 -0
- data/lib/frodata/properties/decimal.rb +50 -0
- data/lib/frodata/properties/enum.rb +62 -0
- data/lib/frodata/properties/float.rb +67 -0
- data/lib/frodata/properties/geography.rb +13 -0
- data/lib/frodata/properties/geography/base.rb +162 -0
- data/lib/frodata/properties/geography/line_string.rb +33 -0
- data/lib/frodata/properties/geography/point.rb +31 -0
- data/lib/frodata/properties/geography/polygon.rb +38 -0
- data/lib/frodata/properties/guid.rb +17 -0
- data/lib/frodata/properties/integer.rb +107 -0
- data/lib/frodata/properties/number.rb +14 -0
- data/lib/frodata/properties/string.rb +72 -0
- data/lib/frodata/properties/time.rb +40 -0
- data/lib/frodata/properties/time_of_day.rb +27 -0
- data/lib/frodata/property.rb +139 -0
- data/lib/frodata/property_registry.rb +41 -0
- data/lib/frodata/query.rb +233 -0
- data/lib/frodata/query/criteria.rb +92 -0
- data/lib/frodata/query/criteria/comparison_operators.rb +49 -0
- data/lib/frodata/query/criteria/date_functions.rb +61 -0
- data/lib/frodata/query/criteria/geography_functions.rb +21 -0
- data/lib/frodata/query/criteria/lambda_operators.rb +27 -0
- data/lib/frodata/query/criteria/string_functions.rb +40 -0
- data/lib/frodata/query/in_batches.rb +58 -0
- data/lib/frodata/railtie.rb +19 -0
- data/lib/frodata/schema.rb +155 -0
- data/lib/frodata/schema/complex_type.rb +79 -0
- data/lib/frodata/schema/enum_type.rb +95 -0
- data/lib/frodata/service.rb +254 -0
- data/lib/frodata/service/request.rb +85 -0
- data/lib/frodata/service/response.rb +162 -0
- data/lib/frodata/service/response/atom.rb +40 -0
- data/lib/frodata/service/response/json.rb +41 -0
- data/lib/frodata/service/response/plain.rb +36 -0
- data/lib/frodata/service/response/xml.rb +40 -0
- data/lib/frodata/service_registry.rb +52 -0
- data/lib/frodata/version.rb +3 -0
- data/spec/fixtures/files/entity_to_xml.xml +17 -0
- data/spec/fixtures/files/error.xml +5 -0
- data/spec/fixtures/files/metadata.xml +150 -0
- data/spec/fixtures/files/product_0.json +10 -0
- data/spec/fixtures/files/product_0.xml +28 -0
- data/spec/fixtures/files/products.json +106 -0
- data/spec/fixtures/files/products.xml +308 -0
- data/spec/fixtures/files/supplier_0.json +26 -0
- data/spec/fixtures/files/supplier_0.xml +32 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs.yml +1635 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml +183 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml +256 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/new_entry.yml +185 -0
- data/spec/fixtures/vcr_cassettes/entity_specs.yml +285 -0
- data/spec/fixtures/vcr_cassettes/navigation_property_proxy_specs.yml +346 -0
- data/spec/fixtures/vcr_cassettes/query/result_specs.yml +189 -0
- data/spec/fixtures/vcr_cassettes/query_specs.yml +1060 -0
- data/spec/fixtures/vcr_cassettes/schema/complex_type_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/service/request_specs.yml +193 -0
- data/spec/fixtures/vcr_cassettes/service_registry_specs.yml +129 -0
- data/spec/fixtures/vcr_cassettes/service_specs.yml +127 -0
- data/spec/fixtures/vcr_cassettes/usage_example_specs.yml +1330 -0
- data/spec/frodata/entity/shared_examples.rb +82 -0
- data/spec/frodata/entity_container_spec.rb +38 -0
- data/spec/frodata/entity_set_spec.rb +168 -0
- data/spec/frodata/entity_spec.rb +151 -0
- data/spec/frodata/errors_spec.rb +48 -0
- data/spec/frodata/navigation_property/proxy_spec.rb +44 -0
- data/spec/frodata/navigation_property_spec.rb +55 -0
- data/spec/frodata/properties/binary_spec.rb +50 -0
- data/spec/frodata/properties/boolean_spec.rb +72 -0
- data/spec/frodata/properties/collection_spec.rb +44 -0
- data/spec/frodata/properties/date_spec.rb +23 -0
- data/spec/frodata/properties/date_time_offset_spec.rb +30 -0
- data/spec/frodata/properties/date_time_spec.rb +23 -0
- data/spec/frodata/properties/decimal_spec.rb +51 -0
- data/spec/frodata/properties/float_spec.rb +45 -0
- data/spec/frodata/properties/geography/line_string_spec.rb +33 -0
- data/spec/frodata/properties/geography/point_spec.rb +29 -0
- data/spec/frodata/properties/geography/polygon_spec.rb +55 -0
- data/spec/frodata/properties/geography/shared_examples.rb +72 -0
- data/spec/frodata/properties/guid_spec.rb +17 -0
- data/spec/frodata/properties/integer_spec.rb +58 -0
- data/spec/frodata/properties/string_spec.rb +46 -0
- data/spec/frodata/properties/time_of_day_spec.rb +23 -0
- data/spec/frodata/properties/time_spec.rb +15 -0
- data/spec/frodata/property_registry_spec.rb +16 -0
- data/spec/frodata/property_spec.rb +71 -0
- data/spec/frodata/query/criteria_spec.rb +229 -0
- data/spec/frodata/query_spec.rb +199 -0
- data/spec/frodata/schema/complex_type_spec.rb +96 -0
- data/spec/frodata/schema/enum_type_spec.rb +112 -0
- data/spec/frodata/schema_spec.rb +97 -0
- data/spec/frodata/service/request_spec.rb +49 -0
- data/spec/frodata/service/response_spec.rb +85 -0
- data/spec/frodata/service_registry_spec.rb +18 -0
- data/spec/frodata/service_spec.rb +191 -0
- data/spec/frodata/usage_example_spec.rb +188 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/coverage.rb +2 -0
- data/spec/support/vcr.rb +9 -0
- metadata +401 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Binary FrOData type.
|
|
4
|
+
class Binary < FrOData::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [Integer,nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
@value.to_i
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value [0,1,Boolean]
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(new_value)
|
|
19
|
+
@value = parse_value(new_value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The FrOData type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Binary'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Value to be used in URLs.
|
|
28
|
+
# @return [String]
|
|
29
|
+
def url_value
|
|
30
|
+
"binary'#{value}'"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def parse_value(value)
|
|
36
|
+
if value == 0 || value == '0' || value == false
|
|
37
|
+
'0'
|
|
38
|
+
else
|
|
39
|
+
'1'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def validate(value)
|
|
44
|
+
unless [0,1,'0','1',true,false].include?(value)
|
|
45
|
+
validation_error 'Value is outside accepted range: 0 or 1'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Boolean FrOData type.
|
|
4
|
+
class Boolean < FrOData::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [Boolean, nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
(@value == 'true' || @value == '1')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value [Boolean]
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(new_value)
|
|
19
|
+
@value = new_value.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The FrOData type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Boolean'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate(value)
|
|
30
|
+
return if value.nil? && allows_nil?
|
|
31
|
+
unless [0,1,'0','1','true','false',true,false].include?(value)
|
|
32
|
+
validation_error 'Value is outside accepted range: true or false'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Collection FrOData type.
|
|
4
|
+
class Collection < FrOData::Property
|
|
5
|
+
# Overriding default constructor to avoid converting
|
|
6
|
+
# value to string.
|
|
7
|
+
# TODO: Make this the default for all property types?
|
|
8
|
+
def initialize(name, value, options = {})
|
|
9
|
+
super(name, value, options)
|
|
10
|
+
self.value = value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def value
|
|
14
|
+
if @value.nil?
|
|
15
|
+
nil
|
|
16
|
+
else
|
|
17
|
+
@value.map(&:value)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def value=(value)
|
|
22
|
+
if value.nil? && allows_nil?
|
|
23
|
+
@value = nil
|
|
24
|
+
elsif value.respond_to?(:map)
|
|
25
|
+
@value = value.map.with_index do |element, index|
|
|
26
|
+
type_class.new("#{name}[#{index}]", element)
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
validation_error 'Value must be an array'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def url_value
|
|
34
|
+
'[' + @value.map(&:url_value).join(',') + ']'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def type
|
|
38
|
+
"Collection(#{value_type})"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def value_type
|
|
42
|
+
options[:value_type] || 'Edm.String'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def type_class
|
|
46
|
+
FrOData::PropertyRegistry[value_type]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Abstract base class for FrOData ComplexTypes
|
|
4
|
+
# @see [FrOData::Schema::ComplexType]
|
|
5
|
+
class Complex < FrOData::Property
|
|
6
|
+
def initialize(name, value, options = {})
|
|
7
|
+
super(name, value, options)
|
|
8
|
+
init_properties
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Returns the property value, properly typecast
|
|
12
|
+
# @return [Hash, nil]
|
|
13
|
+
def value
|
|
14
|
+
if allows_nil? && properties.values.all?(&:nil?)
|
|
15
|
+
nil
|
|
16
|
+
else
|
|
17
|
+
Hash[properties.map { |key, value| [key, value.value] }]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Sets the property value
|
|
22
|
+
# @params new_value [Hash]
|
|
23
|
+
def value=(new_value)
|
|
24
|
+
validate(new_value)
|
|
25
|
+
if new_value.nil?
|
|
26
|
+
property_names.each { |name| self[name] = nil }
|
|
27
|
+
else
|
|
28
|
+
property_names.each { |name| self[name] = new_value[name] }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns a list of this ComplexType's property names.
|
|
33
|
+
# @return [Array<String>]
|
|
34
|
+
def property_names
|
|
35
|
+
@property_names ||= properties.keys
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns the value of the requested property.
|
|
39
|
+
# @param property_name [to_s]
|
|
40
|
+
# @return [*]
|
|
41
|
+
def [](property_name)
|
|
42
|
+
properties[property_name.to_s].value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Sets the value of the named property.
|
|
46
|
+
# @param property_name [to_s]
|
|
47
|
+
# @param value [*]
|
|
48
|
+
# @return [*]
|
|
49
|
+
def []=(property_name, value)
|
|
50
|
+
properties[property_name.to_s].value = value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns the XML representation of the property to the supplied XML
|
|
54
|
+
# builder.
|
|
55
|
+
# @param xml_builder [Nokogiri::XML::Builder]
|
|
56
|
+
def to_xml(xml_builder)
|
|
57
|
+
attributes = {
|
|
58
|
+
'metadata:type' => type,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
xml_builder['data'].send(name.to_sym, attributes) do
|
|
62
|
+
properties.each do |name, property|
|
|
63
|
+
property.to_xml(xml_builder)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Creates a new property instance from an XML element
|
|
69
|
+
# @param property_xml [Nokogiri::XML::Element]
|
|
70
|
+
# @param options [Hash]
|
|
71
|
+
# @return [FrOData::Property]
|
|
72
|
+
def self.from_xml(property_xml, options = {})
|
|
73
|
+
nodes = property_xml.element_children
|
|
74
|
+
props = Hash[nodes.map { |el| [el.name, el.content] }]
|
|
75
|
+
new(property_xml.name, props.to_json, options)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def complex_type
|
|
81
|
+
raise NotImplementedError, 'Subclass must override'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def properties
|
|
85
|
+
@properties
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def init_properties
|
|
89
|
+
@properties = complex_type.send(:collect_properties)
|
|
90
|
+
set_properties(JSON.parse(@value)) unless @value.nil?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def set_properties(new_properties)
|
|
94
|
+
property_names.each do |prop_name|
|
|
95
|
+
self[prop_name] = new_properties[prop_name]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def validate(value)
|
|
100
|
+
return if value.nil? && allows_nil?
|
|
101
|
+
raise ArgumentError, 'Value must be a Hash' unless value.is_a?(Hash)
|
|
102
|
+
value.keys.each do |name|
|
|
103
|
+
unless property_names.include?(name) || name =~ /@odata/
|
|
104
|
+
raise ArgumentError, "Invalid property #{name}"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def validate_options(options)
|
|
110
|
+
raise ArgumentError, 'Type is required' unless options[:type]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'frodata/properties/date_time'
|
|
2
|
+
|
|
3
|
+
module FrOData
|
|
4
|
+
module Properties
|
|
5
|
+
# Defines the Date FrOData type.
|
|
6
|
+
class Date < FrOData::Properties::DateTime
|
|
7
|
+
# The FrOData type name
|
|
8
|
+
def type
|
|
9
|
+
'Edm.Date'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def url_value
|
|
13
|
+
@value
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
|
|
18
|
+
def date_class
|
|
19
|
+
::Date
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def strptime_format
|
|
23
|
+
'%Y-%m-%d'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the DateTime FrOData type.
|
|
4
|
+
class DateTime < FrOData::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [DateTime, nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && allows_nil?
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
begin
|
|
12
|
+
date_class.strptime(@value, strptime_format)
|
|
13
|
+
rescue ArgumentError
|
|
14
|
+
date_class.parse(@value)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Sets the property value
|
|
20
|
+
# @params new_value [DateTime]
|
|
21
|
+
def value=(new_value)
|
|
22
|
+
validate(new_value)
|
|
23
|
+
@value = parse_value(new_value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The FrOData type name
|
|
27
|
+
def type
|
|
28
|
+
'Edm.DateTime'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Value to be used in JSON.
|
|
32
|
+
# @return [String]
|
|
33
|
+
def xml_value
|
|
34
|
+
@value.andand.sub(/[\+\-]00:00$/, 'Z')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Value to be used in JSON.
|
|
38
|
+
# @return [String]
|
|
39
|
+
def json_value
|
|
40
|
+
xml_value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Value to be used in URLs.
|
|
44
|
+
# @return [String]
|
|
45
|
+
def url_value
|
|
46
|
+
xml_value
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
# Specifies date/time implementation to use
|
|
52
|
+
def date_class
|
|
53
|
+
::DateTime
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Specifies the date/time format string used for `strptime`
|
|
57
|
+
def strptime_format
|
|
58
|
+
#'%Y-%m-%dT%H:%M:%S.%L'
|
|
59
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def validate(value)
|
|
63
|
+
begin
|
|
64
|
+
return if value.nil? && allows_nil?
|
|
65
|
+
return if value.is_a?(date_class)
|
|
66
|
+
date_class.parse(value)
|
|
67
|
+
rescue
|
|
68
|
+
validation_error "Value '#{value}' is not a date time format that can be parsed"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse_value(value)
|
|
73
|
+
return value if value.nil? && allows_nil?
|
|
74
|
+
if value.is_a?(date_class)
|
|
75
|
+
parsed_value = value
|
|
76
|
+
else
|
|
77
|
+
parsed_value = date_class.parse(value)
|
|
78
|
+
end
|
|
79
|
+
parsed_value.strftime(strptime_format)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the DateTimeOffset FrOData type.
|
|
4
|
+
class DateTimeOffset < FrOData::Properties::DateTime
|
|
5
|
+
# The FrOData type name
|
|
6
|
+
def type
|
|
7
|
+
'Edm.DateTimeOffset'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def strptime_format
|
|
13
|
+
'%Y-%m-%dT%H:%M:%S%:z'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Defines the Decimal FrOData type.
|
|
4
|
+
class Decimal < FrOData::Property
|
|
5
|
+
# Returns the property value, properly typecast
|
|
6
|
+
# @return [BigDecimal,nil]
|
|
7
|
+
def value
|
|
8
|
+
if (@value.nil? || @value.empty?) && (strict? && allows_nil?)
|
|
9
|
+
nil
|
|
10
|
+
else
|
|
11
|
+
BigDecimal(@value)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the property value
|
|
16
|
+
# @params new_value something BigDecimal() can parse
|
|
17
|
+
def value=(new_value)
|
|
18
|
+
validate(BigDecimal(new_value.to_s))
|
|
19
|
+
@value = new_value.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The FrOData type name
|
|
23
|
+
def type
|
|
24
|
+
'Edm.Decimal'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Value to be used in URLs.
|
|
28
|
+
# @return [String]
|
|
29
|
+
def url_value
|
|
30
|
+
"#{value.to_f}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def validate(value)
|
|
36
|
+
if value > max_value || value < min_value || value.precs.first > 29
|
|
37
|
+
validation_error "Value is outside accepted range: #{min_value} to #{max_value}, or has more than 29 significant digits"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def min_value
|
|
42
|
+
@min ||= BigDecimal(-7.9 * (10**28), 2)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def max_value
|
|
46
|
+
@max ||= BigDecimal(7.9 * (10**28), 2)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module FrOData
|
|
2
|
+
module Properties
|
|
3
|
+
# Abstract base class for FrOData EnumTypes
|
|
4
|
+
# @see [FrOData::Schema::EnumType]
|
|
5
|
+
class Enum < FrOData::Property
|
|
6
|
+
# Returns the property value, properly typecast
|
|
7
|
+
# @return [String, nil]
|
|
8
|
+
def value
|
|
9
|
+
if @value.nil? && allows_nil?
|
|
10
|
+
nil
|
|
11
|
+
else
|
|
12
|
+
@value
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Sets the property value
|
|
17
|
+
# @params new_value [String]
|
|
18
|
+
def value=(new_value)
|
|
19
|
+
parsed_value = validate(new_value)
|
|
20
|
+
@value = is_flags? ? parsed_value : parsed_value.first
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Value to be used in URLs.
|
|
24
|
+
# @return [String]
|
|
25
|
+
def url_value
|
|
26
|
+
"#{type}'#{@value}'"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def members
|
|
32
|
+
raise NotImplementedError, 'Subclass must override'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def validate(value)
|
|
36
|
+
return [] if value.nil? && allows_nil?
|
|
37
|
+
values = parse_value(value)
|
|
38
|
+
|
|
39
|
+
if values.length > 1 && !is_flags?
|
|
40
|
+
raise ArgumentError, 'Multiple values are not allowed for this property'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
values.map do |value|
|
|
44
|
+
if members.keys.include?(value)
|
|
45
|
+
members[value]
|
|
46
|
+
elsif members.values.include?(value)
|
|
47
|
+
value
|
|
48
|
+
else
|
|
49
|
+
validation_error "Value must be one of #{members.to_a}, but was: '#{value}'"
|
|
50
|
+
end
|
|
51
|
+
end.compact
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def parse_value(value)
|
|
55
|
+
return nil if value.nil?
|
|
56
|
+
value.to_s.split(',').map(&:strip).map do |val|
|
|
57
|
+
val =~ /^[0-9]+$/ ? val.to_i : val
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|