nidyx 0.1.0
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.
- data/LICENSE +21 -0
- data/README.md +146 -0
- data/bin/nidyx +125 -0
- data/lib/nidyx/common.rb +54 -0
- data/lib/nidyx/core_ext/string.rb +12 -0
- data/lib/nidyx/generator.rb +17 -0
- data/lib/nidyx/mapper.rb +19 -0
- data/lib/nidyx/model.rb +12 -0
- data/lib/nidyx/objc/implementation.rb +33 -0
- data/lib/nidyx/objc/interface.rb +20 -0
- data/lib/nidyx/objc/mapper.rb +44 -0
- data/lib/nidyx/objc/model.rb +12 -0
- data/lib/nidyx/objc/model_base.rb +31 -0
- data/lib/nidyx/objc/property.rb +174 -0
- data/lib/nidyx/output.rb +25 -0
- data/lib/nidyx/parse_constants.rb +29 -0
- data/lib/nidyx/parser.rb +188 -0
- data/lib/nidyx/pointer.rb +17 -0
- data/lib/nidyx/property.rb +52 -0
- data/lib/nidyx/reader.rb +45 -0
- data/lib/nidyx/version.rb +3 -0
- data/lib/nidyx.rb +1 -0
- data/test/nidyx/core_ext/test_string.rb +40 -0
- data/test/nidyx/objc/test_model_base.rb +26 -0
- data/test/nidyx/objc/test_property.rb +237 -0
- data/test/nidyx/test_common.rb +102 -0
- data/test/nidyx/test_comparison.rb +64 -0
- data/test/nidyx/test_parser.rb +460 -0
- data/test/nidyx/test_pointer.rb +42 -0
- data/test/nidyx/test_property.rb +38 -0
- metadata +134 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module Nidyx
|
4
|
+
class ObjCProperty
|
5
|
+
attr_reader :name, :attributes, :type, :type_name, :desc, :getter_override,
|
6
|
+
:protocols
|
7
|
+
|
8
|
+
class UnsupportedEnumTypeError < StandardError; end
|
9
|
+
|
10
|
+
# @param property [Property] generic property
|
11
|
+
def initialize(property)
|
12
|
+
@name = property.name
|
13
|
+
@optional = property.optional
|
14
|
+
@desc = property.description
|
15
|
+
|
16
|
+
@getter_override = process_getter_override(name)
|
17
|
+
@type = process_type(property)
|
18
|
+
@attributes = ATTRIBUTES[@type]
|
19
|
+
@type_name = lookup_type_name(@type, property.class_name)
|
20
|
+
|
21
|
+
@protocols = []
|
22
|
+
@protocols += property.collection_types if property.collection_types
|
23
|
+
@protocols << "Optional" if @optional
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Boolean] true if the obj-c property type is an object
|
27
|
+
def is_obj?
|
28
|
+
OBJECTS.include?(self.type)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Boolean] true if the property has protocols
|
32
|
+
def has_protocols?
|
33
|
+
!@protocols.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String] the property's protocols, comma separated
|
37
|
+
def protocols_string
|
38
|
+
@protocols.join(", ")
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
PRIMITIVE_ATTRIBUTES = "assign, nonatomic"
|
44
|
+
OBJECT_ATTRIBUTES = "strong, nonatomic"
|
45
|
+
|
46
|
+
ATTRIBUTES = {
|
47
|
+
:array => OBJECT_ATTRIBUTES,
|
48
|
+
:boolean => PRIMITIVE_ATTRIBUTES,
|
49
|
+
:integer => PRIMITIVE_ATTRIBUTES,
|
50
|
+
:unsigned => PRIMITIVE_ATTRIBUTES,
|
51
|
+
:number => PRIMITIVE_ATTRIBUTES,
|
52
|
+
:number_obj => OBJECT_ATTRIBUTES,
|
53
|
+
:string => OBJECT_ATTRIBUTES,
|
54
|
+
:object => OBJECT_ATTRIBUTES,
|
55
|
+
:id => OBJECT_ATTRIBUTES
|
56
|
+
}
|
57
|
+
|
58
|
+
# Objective-C types
|
59
|
+
# :object intentionally omitted
|
60
|
+
TYPES = {
|
61
|
+
:array => "NSArray",
|
62
|
+
:boolean => "BOOL",
|
63
|
+
:integer => "NSInteger",
|
64
|
+
:unsigned => "NSUInteger",
|
65
|
+
:number => "double",
|
66
|
+
:number_obj => "NSNumber",
|
67
|
+
:string => "NSString",
|
68
|
+
:id => "id"
|
69
|
+
}
|
70
|
+
|
71
|
+
# Hash and Array intentionally omitted
|
72
|
+
ENUM_TYPES = {
|
73
|
+
Fixnum => :integer,
|
74
|
+
String => :string,
|
75
|
+
NilClass => :null,
|
76
|
+
Float => :number,
|
77
|
+
TrueClass => :boolean,
|
78
|
+
FalseClass => :boolean
|
79
|
+
}
|
80
|
+
|
81
|
+
OBJECTS = Set.new [:array, :number_obj, :string, :object, :id]
|
82
|
+
|
83
|
+
SIMPLE_NUMBERS = Set.new [:unsigned, :integer, :number]
|
84
|
+
|
85
|
+
BOXABLE_NUMBERS = SIMPLE_NUMBERS + [:boolean]
|
86
|
+
|
87
|
+
FORBIDDEN_PROPERTY_PREFIXES = ["new", "copy"]
|
88
|
+
|
89
|
+
# @param type [Symbol] an obj-c property type
|
90
|
+
# @param class_name [String] an object's type name
|
91
|
+
# @return [String] the property's type name
|
92
|
+
def lookup_type_name(type, class_name)
|
93
|
+
type == :object ? class_name : TYPES[type]
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param property [Property] generic property
|
97
|
+
# @return [Symbol] an obj-c property type
|
98
|
+
def process_type(property)
|
99
|
+
return process_enum_type(property) if property.enum
|
100
|
+
|
101
|
+
type = property.type
|
102
|
+
if type.is_a?(Set)
|
103
|
+
process_array_type(type, property)
|
104
|
+
else
|
105
|
+
process_simple_type(type, property)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# @param property [Property] generic property
|
111
|
+
# @return [Symbol] an obj-c property type
|
112
|
+
def process_enum_type(property)
|
113
|
+
enum = property.enum
|
114
|
+
|
115
|
+
# map enum to a set of types
|
116
|
+
types = enum.map { |a| a.class }
|
117
|
+
raise UnsupportedEnumTypeError unless (types & [ Array, Hash ]).empty?
|
118
|
+
types = Set.new(types.map { |t| ENUM_TYPES[t] })
|
119
|
+
|
120
|
+
process_array_type(types, property)
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param type [Symbol] a property type symbol
|
124
|
+
# @param property [Property] generic property
|
125
|
+
# @return [Symbol] an obj-c property type
|
126
|
+
def process_simple_type(type, property)
|
127
|
+
case type
|
128
|
+
when :boolean, :number, :integer
|
129
|
+
return :number_obj if @optional
|
130
|
+
if type == :integer && property.minimum && property.minimum >= 0
|
131
|
+
return :unsigned
|
132
|
+
end
|
133
|
+
type
|
134
|
+
|
135
|
+
when :null
|
136
|
+
@optional = true
|
137
|
+
:id
|
138
|
+
|
139
|
+
when :object
|
140
|
+
property.has_properties? ? :object : :id
|
141
|
+
|
142
|
+
else
|
143
|
+
type
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# @param type [Set] an array of property types
|
148
|
+
# @param property [Property] generic property
|
149
|
+
# @return [Symbol] an obj-c property type
|
150
|
+
def process_array_type(types, property)
|
151
|
+
# if the key is optional
|
152
|
+
@optional = true if types.delete?(:null)
|
153
|
+
|
154
|
+
# single optional type
|
155
|
+
return process_simple_type(types.to_a.shift, property) if types.size == 1
|
156
|
+
|
157
|
+
# conjoined number types
|
158
|
+
return :number if types.subset?(SIMPLE_NUMBERS) && !@optional
|
159
|
+
return :number_obj if types.subset?(BOXABLE_NUMBERS)
|
160
|
+
|
161
|
+
:id
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param name [String] the property name
|
165
|
+
# @return [String, nil] the getter override string if necessary
|
166
|
+
def process_getter_override(name)
|
167
|
+
FORBIDDEN_PROPERTY_PREFIXES.each do |p|
|
168
|
+
return ", getter=get#{name.camelize}" if name.match(/^#{p}[_A-Z].*/)
|
169
|
+
end
|
170
|
+
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/nidyx/output.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Nidyx
|
2
|
+
module Output
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# @param models [Hash] a full hash of models to output
|
6
|
+
# @param dir [String] output directory, defaults to current directory
|
7
|
+
def write(models, dir)
|
8
|
+
path = dir || Dir.getwd
|
9
|
+
models.each { |model| write_file(model, path) }
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# @param model [Hash] all of the files for a specific model, stored in
|
15
|
+
# @param path [String] output directory
|
16
|
+
# a hash by extension
|
17
|
+
def write_file(model, path)
|
18
|
+
model.files.each do |file|
|
19
|
+
File.open(File.join(path, file.file_name), "w") do |f|
|
20
|
+
f.puts file.render
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Nidyx
|
2
|
+
module ParseConstants
|
3
|
+
|
4
|
+
###
|
5
|
+
# Schema key definitions
|
6
|
+
###
|
7
|
+
REF_KEY = "$ref"
|
8
|
+
ENUM_KEY = "enum"
|
9
|
+
TYPE_KEY = "type"
|
10
|
+
DESCRIPTION_KEY = "description"
|
11
|
+
REQUIRED_KEY = "required"
|
12
|
+
PROPERTIES_KEY = "properties"
|
13
|
+
NAME_OVERRIDE_KEY = "nameOverride"
|
14
|
+
ITEMS_KEY = "items"
|
15
|
+
MINIMUM_KEY = "minimum"
|
16
|
+
|
17
|
+
###
|
18
|
+
# Internal schema key definitions
|
19
|
+
###
|
20
|
+
DERIVED_NAME = "__derivedName"
|
21
|
+
COLLECTION_TYPES_KEY = "__collectionTypes"
|
22
|
+
|
23
|
+
###
|
24
|
+
# Object types
|
25
|
+
###
|
26
|
+
OBJECT_TYPE = "object"
|
27
|
+
ARRAY_TYPE = "array"
|
28
|
+
end
|
29
|
+
end
|
data/lib/nidyx/parser.rb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
require "nidyx/common"
|
2
|
+
require "nidyx/parse_constants"
|
3
|
+
require "nidyx/property"
|
4
|
+
require "nidyx/pointer"
|
5
|
+
require "nidyx/model"
|
6
|
+
|
7
|
+
include Nidyx::Common
|
8
|
+
include Nidyx::ParseConstants
|
9
|
+
|
10
|
+
module Nidyx
|
11
|
+
module Parser
|
12
|
+
extend self
|
13
|
+
|
14
|
+
class UnsupportedSchemaError < StandardError; end
|
15
|
+
|
16
|
+
# @param model_prefix [String] the prefix for model names
|
17
|
+
# @param schema [Hash] JSON Schema
|
18
|
+
# @param options [Hash] global application options
|
19
|
+
# @return [Hash] a Hash of ModelData objects
|
20
|
+
def parse(model_prefix, schema, options)
|
21
|
+
# setup parser
|
22
|
+
@class_prefix = model_prefix
|
23
|
+
@options = options
|
24
|
+
@schema = schema
|
25
|
+
@models = {}
|
26
|
+
|
27
|
+
# run model generation
|
28
|
+
generate([], class_name(@class_prefix, nil))
|
29
|
+
@models
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Generates a Model and adds it to the models array.
|
35
|
+
# @param path [Array] the path to an object in the schema
|
36
|
+
# @param name [String] raw model name
|
37
|
+
def generate(path, name)
|
38
|
+
object = get_object(path)
|
39
|
+
|
40
|
+
type = object[TYPE_KEY]
|
41
|
+
if type == OBJECT_TYPE
|
42
|
+
generate_object(path, name)
|
43
|
+
|
44
|
+
elsif type == ARRAY_TYPE
|
45
|
+
generate_top_level_array(path)
|
46
|
+
|
47
|
+
elsif type.is_a?(Array)
|
48
|
+
if type.include?(OBJECT_TYPE)
|
49
|
+
raise UnsupportedSchemaError if type.include?(ARRAY_TYPE)
|
50
|
+
generate_object(path, name)
|
51
|
+
|
52
|
+
elsif type.include?(ARRAY_TYPE)
|
53
|
+
generate_top_leve_array(path)
|
54
|
+
|
55
|
+
else raise UnsupportedSchemaError; end
|
56
|
+
else raise UnsupportedSchemaError; end
|
57
|
+
end
|
58
|
+
|
59
|
+
def generate_object(path, name)
|
60
|
+
@models[name] = model = Nidyx::Model.new(name)
|
61
|
+
required_properties = get_object(path)[REQUIRED_KEY]
|
62
|
+
properties_path = path + [PROPERTIES_KEY]
|
63
|
+
|
64
|
+
get_object(properties_path).keys.each do |key|
|
65
|
+
optional = is_optional?(key, required_properties)
|
66
|
+
property_path = properties_path + [key]
|
67
|
+
model.properties << generate_property(key, property_path, model, optional)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_top_level_array(path)
|
72
|
+
resolve_array_refs(get_object(path))
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param key [String] the key of the property in the JSON Schema
|
76
|
+
# @param path [Array] the path to the aforementioned object in the schema
|
77
|
+
# @param model [Property] the model that owns the property to be generated
|
78
|
+
# @param optional [Boolean] true if the property can be empty or null
|
79
|
+
def generate_property(key, path, model, optional)
|
80
|
+
obj = resolve_reference(path)
|
81
|
+
class_name = obj[DERIVED_NAME]
|
82
|
+
|
83
|
+
if include_type?(obj, OBJECT_TYPE) && obj[PROPERTIES_KEY]
|
84
|
+
model.dependencies << class_name
|
85
|
+
elsif include_type?(obj, ARRAY_TYPE)
|
86
|
+
obj[COLLECTION_TYPES_KEY] = resolve_array_refs(obj)
|
87
|
+
model.dependencies += obj[COLLECTION_TYPES_KEY]
|
88
|
+
end
|
89
|
+
|
90
|
+
name = obj[NAME_OVERRIDE_KEY] || key
|
91
|
+
property = Nidyx::Property.new(name, class_name, optional, obj)
|
92
|
+
property.overriden_name = key if obj[NAME_OVERRIDE_KEY]
|
93
|
+
property
|
94
|
+
end
|
95
|
+
|
96
|
+
# Given a path, which could be at any part of a reference chain, resolve
|
97
|
+
# the immediate schema object. This means:
|
98
|
+
#
|
99
|
+
# - if there is an imediate ref, follow it
|
100
|
+
# - inherit any schema information from the parent reference chain
|
101
|
+
# (unimplemented)
|
102
|
+
#
|
103
|
+
# If we are at the end of a chain, do the following:
|
104
|
+
#
|
105
|
+
# - generate a model for this object if necessary
|
106
|
+
# - add `class_name` to the immediate object when appropriate
|
107
|
+
# - return the immediate object
|
108
|
+
#
|
109
|
+
# @param path [Array] the path to an object in the schema
|
110
|
+
# @param parent [Hash, nil] the merged attributes of the parent reference chain
|
111
|
+
# @return [Hash] a modified schema object with inherited attributes from
|
112
|
+
# it's parents.
|
113
|
+
def resolve_reference(path, parent = nil)
|
114
|
+
obj = get_object(path)
|
115
|
+
ref = obj[REF_KEY]
|
116
|
+
|
117
|
+
# TODO: merge parent and obj into obj (destructive)
|
118
|
+
|
119
|
+
# If we find an immediate reference, chase it and pass the immediate
|
120
|
+
# object as a parent.
|
121
|
+
return resolve_reference_string(ref) if ref
|
122
|
+
|
123
|
+
# If we are dealing with an object, encode it's class name into the
|
124
|
+
# schema and generate it's model if necessary.
|
125
|
+
if include_type?(obj, OBJECT_TYPE) && obj[PROPERTIES_KEY]
|
126
|
+
obj[DERIVED_NAME] = class_name_from_path(@class_prefix, path, @schema)
|
127
|
+
generate(path, obj[DERIVED_NAME]) unless @models.has_key?(obj[DERIVED_NAME])
|
128
|
+
end
|
129
|
+
|
130
|
+
obj
|
131
|
+
end
|
132
|
+
|
133
|
+
# Resolves any references burried in the `items` property of an array
|
134
|
+
# definition. Returns a list of collection types in the array.
|
135
|
+
# @param obj [Hash] the array property schema
|
136
|
+
# @return [Array] list of types in the array
|
137
|
+
def resolve_array_refs(obj)
|
138
|
+
items = obj[ITEMS_KEY]
|
139
|
+
types = []
|
140
|
+
|
141
|
+
case items
|
142
|
+
when Array
|
143
|
+
items.each do |i|
|
144
|
+
resolve_reference_string(i[REF_KEY])
|
145
|
+
types << class_name_from_ref(i[REF_KEY])
|
146
|
+
end
|
147
|
+
when Hash
|
148
|
+
resolve_reference_string(items[REF_KEY])
|
149
|
+
types << class_name_from_ref(items[REF_KEY])
|
150
|
+
end
|
151
|
+
|
152
|
+
types.compact
|
153
|
+
end
|
154
|
+
|
155
|
+
def class_name_from_ref(ref)
|
156
|
+
class_name_from_path(@class_prefix, Nidyx::Pointer.new(ref).path, @schema) if ref
|
157
|
+
end
|
158
|
+
|
159
|
+
# Resolves a reference as a plain JSON Pointer string.
|
160
|
+
# @param ref [String] reference in json pointer format
|
161
|
+
# @return [Hash] a modified schema object with inherited attributes from
|
162
|
+
# it's parents.
|
163
|
+
def resolve_reference_string(ref)
|
164
|
+
resolve_reference(Nidyx::Pointer.new(ref).path) if ref
|
165
|
+
end
|
166
|
+
|
167
|
+
# @param path [Array] the path to an object in the global schema
|
168
|
+
# @return [Hash] a object containing JSON schema
|
169
|
+
def get_object(path)
|
170
|
+
object_at_path(path, @schema)
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param key [String] the id of a specific property
|
174
|
+
# @param required_keys [Array] an array of the required property keys
|
175
|
+
# @return true if the property is optional
|
176
|
+
def is_optional?(key, required_keys)
|
177
|
+
!(required_keys && required_keys.include?(key))
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param type_obj [Array, String] the JSON Schema type
|
181
|
+
# @param type [String] a string type to test
|
182
|
+
# @param true if the string type is a valid type according type object
|
183
|
+
def include_type?(obj, type)
|
184
|
+
type_obj = obj[TYPE_KEY]
|
185
|
+
type_obj.is_a?(Array) ? type_obj.include?(type) : type_obj == type
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# JSON Pointer
|
2
|
+
module Nidyx
|
3
|
+
class Pointer
|
4
|
+
attr_reader :source, :path
|
5
|
+
|
6
|
+
def initialize(str)
|
7
|
+
match = /^(?<source>.*)#\/*(?<path>.*)$/.match(str)
|
8
|
+
@source = match[:source]
|
9
|
+
@path = match[:path].split("/")
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
puts "source: #{source}"
|
14
|
+
puts "path: #{path}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "set"
|
2
|
+
require "nidyx/parse_constants"
|
3
|
+
|
4
|
+
include Nidyx::ParseConstants
|
5
|
+
|
6
|
+
module Nidyx
|
7
|
+
class Property
|
8
|
+
attr_accessor :overriden_name
|
9
|
+
attr_reader :name, :class_name, :optional, :type, :description, :enum,
|
10
|
+
:collection_types, :minimum
|
11
|
+
|
12
|
+
class UndefinedTypeError < StandardError; end
|
13
|
+
class NonArrayEnumError < StandardError; end
|
14
|
+
class EmptyEnumError < StandardError; end
|
15
|
+
|
16
|
+
def initialize(name, class_name, optional, obj)
|
17
|
+
@name = name.camelize(false)
|
18
|
+
@class_name = class_name
|
19
|
+
@optional = optional
|
20
|
+
@enum = obj[ENUM_KEY]
|
21
|
+
@type = process_type(obj[TYPE_KEY], @enum)
|
22
|
+
@description = obj[DESCRIPTION_KEY]
|
23
|
+
@properties = obj[PROPERTIES_KEY]
|
24
|
+
@collection_types = obj[COLLECTION_TYPES_KEY]
|
25
|
+
@minimum = obj[MINIMUM_KEY]
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_properties?
|
29
|
+
!!@properties
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def process_type(type, enum)
|
35
|
+
if enum
|
36
|
+
raise NonArrayEnumError unless @enum.is_a?(Array)
|
37
|
+
raise EmptyEnumError if @enum.empty?
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
case type
|
42
|
+
when Array
|
43
|
+
raise UndefinedTypeError if type.empty?
|
44
|
+
Set.new(type.map { |t| t.to_sym })
|
45
|
+
when String
|
46
|
+
type.to_sym
|
47
|
+
else
|
48
|
+
raise UndefinedTypeError
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/nidyx/reader.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "json"
|
2
|
+
require "nidyx/parse_constants"
|
3
|
+
|
4
|
+
include Nidyx::ParseConstants
|
5
|
+
|
6
|
+
module Nidyx
|
7
|
+
module Reader
|
8
|
+
extend self
|
9
|
+
|
10
|
+
class EmptySchemaError < StandardError; end
|
11
|
+
|
12
|
+
# Reads JSON from a file
|
13
|
+
# @param path [String] path of the file to read
|
14
|
+
# @return [Hash] the parsed JSON
|
15
|
+
def read(path)
|
16
|
+
schema = nil
|
17
|
+
|
18
|
+
begin
|
19
|
+
# TODO: validate this is legitimate JSON Schema
|
20
|
+
schema = JSON.parse(IO.read(path))
|
21
|
+
raise EmptySchemaError if empty_schema?(schema)
|
22
|
+
rescue JSON::JSONError => e
|
23
|
+
puts "Encountered an error reading JSON from #{path}"
|
24
|
+
puts e.message
|
25
|
+
exit 1
|
26
|
+
rescue EmptySchemaError
|
27
|
+
puts "Schema read from #{path} is empty"
|
28
|
+
exit 1
|
29
|
+
rescue StandardError => e
|
30
|
+
puts e.message
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
schema
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param schema [Hash] an object containing JSON schema
|
38
|
+
# @return [Boolean] true if the schema is empty
|
39
|
+
def empty_schema?(schema)
|
40
|
+
props = schema[PROPERTIES_KEY]
|
41
|
+
items = schema[ITEMS_KEY]
|
42
|
+
(!props || props.empty?) && (!items || items.empty?)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/nidyx.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "nidyx/core_ext/string.rb"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "nidyx"
|
3
|
+
|
4
|
+
class TestCoreExt < Minitest::Test
|
5
|
+
def test_camelize
|
6
|
+
assert_equal("CamelCaseString", "camelCaseString".camelize)
|
7
|
+
assert_equal("CamelCaseString", "camel_case_string".camelize)
|
8
|
+
assert_equal("CamelCaseString", "Camel_Case_String".camelize)
|
9
|
+
assert_equal("CamelCaseString", "camel_Case_STRING".camelize)
|
10
|
+
assert_equal("1IsTheLoneliestNumber", "1_is_the_loneliest_number".camelize)
|
11
|
+
assert_equal("CCString", "CCString".camelize)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_camelize_with_optional_param
|
15
|
+
assert_equal("CamelCaseString", "camelCaseString".camelize(true))
|
16
|
+
assert_equal("camelCaseString", "CamelCaseString".camelize(false))
|
17
|
+
assert_equal("camelCaseString", "camel_case_string".camelize(false))
|
18
|
+
assert_equal("camelCaseString", "camel_case_string".camelize(false))
|
19
|
+
assert_equal("camelCaseString", "Camel_Case_String".camelize(false))
|
20
|
+
assert_equal("camelCaseString", "camel_Case_STRING".camelize(false))
|
21
|
+
assert_equal("1IsTheLoneliestNumber", "1_is_the_loneliest_number".camelize(false))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_camelize_unchanged
|
25
|
+
assert_equal("CamelCaseString", "CamelCaseString".camelize)
|
26
|
+
assert_equal("CamelCaseString", "CamelCaseString".camelize(true))
|
27
|
+
assert_equal("camelCaseString", "camelCaseString".camelize(false))
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_camelize_with_plain_numbers
|
31
|
+
assert_equal("123121151", "123121151".camelize)
|
32
|
+
assert_equal("123121151", "123121151".camelize(false))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_camelize_not_destructive
|
36
|
+
string = "camel_case_string"
|
37
|
+
assert_equal("CamelCaseString", string.camelize)
|
38
|
+
assert_equal("camel_case_string", string)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "nidyx/objc/model_base"
|
3
|
+
|
4
|
+
class TestModelBase < Minitest::Test
|
5
|
+
|
6
|
+
MOCK_OPTS = {
|
7
|
+
:author => "test_author",
|
8
|
+
:company => "test_company",
|
9
|
+
:project => "test_project"
|
10
|
+
}
|
11
|
+
|
12
|
+
def test_empty_options
|
13
|
+
model = Nidyx::ObjCModelBase.new("ModelName", {})
|
14
|
+
assert_equal("ModelName", model.name)
|
15
|
+
assert_equal(nil, model.author)
|
16
|
+
assert_equal(nil, model.owner)
|
17
|
+
assert_equal(nil, model.project)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_full_options
|
21
|
+
model = Nidyx::ObjCModelBase.new("ModelName", MOCK_OPTS)
|
22
|
+
assert_equal("test_author", model.author)
|
23
|
+
assert_equal("test_company", model.owner)
|
24
|
+
assert_equal("test_project", model.project)
|
25
|
+
end
|
26
|
+
end
|