nidyx 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|