metamodel 0.0.5 → 0.1.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 +4 -4
- data/README.md +8 -8
- data/lib/metamodel/command/build/parser.rb +29 -6
- data/lib/metamodel/command/build/renderer.rb +3 -2
- data/lib/metamodel/command/build.rb +30 -3
- data/lib/metamodel/command/generate.rb +2 -2
- data/lib/metamodel/config.rb +1 -1
- data/lib/metamodel/model/model.rb +104 -0
- data/lib/metamodel/model/{cocoa_property.rb → property.rb} +33 -5
- data/lib/metamodel/template/{attributes.swift.erb → attributes.swift} +2 -2
- data/lib/metamodel/template/foreign_key.swift +54 -0
- data/lib/metamodel/template/instance_methods.swift +47 -0
- data/lib/metamodel/template/{json.swift.erb → json.swift} +2 -6
- data/lib/metamodel/template/{metamodel.swift.erb → metamodel.swift} +24 -13
- data/lib/metamodel/template/{model_query.swift.erb → model_query.swift} +4 -4
- data/lib/metamodel/template/{model_relation.swift.erb → model_relation.swift} +15 -2
- data/lib/metamodel/template/{recordable.swift.erb → recordable.swift} +1 -1
- data/lib/metamodel/template/{static_methods.swift.erb → static_methods.swift} +9 -7
- data/lib/metamodel/version.rb +1 -1
- metadata +16 -16
- data/lib/metamodel/model/cocoa_model.rb +0 -79
- data/lib/metamodel/model/property_constructor.rb +0 -31
- data/lib/metamodel/template/instance_methods.swift.erb +0 -38
- /data/lib/metamodel/template/{file_header.swift.erb → file_header.swift} +0 -0
- /data/lib/metamodel/template/{initialize.swift.erb → initialize.swift} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d443b7aba6c0b4f80775f5d7e785d571cbcaee3
|
4
|
+
data.tar.gz: 0a124cd657c3c8e1584d5a106666077cebeafab8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a56c26ba55af301427b5bc9c496230e3a5fb305e36b77360986e21be2fe5e5fc00339cbe3c2393c8e8d5aca3c42c24c2a39a2a1a7fa97bcc8f1be3b74007412c
|
7
|
+
data.tar.gz: f4c5d900b9c36ea62a24c481cd2c47e7da71402b52f2e1b176f93752bfa44fb57df95632830dff20ee8775a6745c6e2a7487fecd11c91d701d1c5a0f2232a81c
|
data/README.md
CHANGED
@@ -5,13 +5,13 @@
|
|
5
5
|
[](https://github.com/draveness/metamodel/blob/master/LICENSE)
|
6
6
|
[](http://rubygems.org/gems/metamodel)
|
7
7
|
|
8
|
-
MetaModel is an iOS framework designed to help developer to deal with data persistent, JSON
|
8
|
+
MetaModel is an iOS framework designed to help developer to deal with data persistent, JSON parsing and a bunch of APIs which provides an approach of handling client side database very easily.
|
9
9
|
|
10
10
|
> MetaModel is under-development, API may constantly change before gets to 1.0.0.
|
11
11
|
|
12
|
-
+ [x] Fastest JSON to model API
|
13
12
|
+ [x] Dealing with database without writing SQL
|
14
13
|
+ [x] Most concise API to retrieve data from persistent level
|
14
|
+
+ [ ] Fastest JSON to model API
|
15
15
|
|
16
16
|
MetaModel provides convenience chainable APIs to manipulate models like ActiveRecord.
|
17
17
|
|
@@ -37,11 +37,11 @@ print(Person.all)
|
|
37
37
|
Use a meta file in `./meta` folder to define your model:
|
38
38
|
|
39
39
|
```ruby
|
40
|
-
define :User do
|
40
|
+
define :User do
|
41
41
|
# define User model like this
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
attr :nickname, :string
|
43
|
+
attr :avatar, :string?
|
44
|
+
attr :email, :string, :unique, default: "default@gmail.com"
|
45
45
|
end
|
46
46
|
```
|
47
47
|
|
@@ -99,10 +99,10 @@ Generating model files
|
|
99
99
|
Generating MetaModel.framework
|
100
100
|
-> MetaModel.framework located in current folder
|
101
101
|
|
102
|
-
[!] Please drag MetaModel.framework into
|
102
|
+
[!] Please drag MetaModel.framework into Embedded Binaries phrase.
|
103
103
|
```
|
104
104
|
|
105
|
-
This command build a `MetaModel.framework` in project root folder, you need to add this framework to **
|
105
|
+
This command build a `MetaModel.framework` in project root folder, you need to add this framework to **Embedded Binaries** phrase which located in `General` tab.
|
106
106
|
|
107
107
|

|
108
108
|
|
@@ -5,9 +5,8 @@ module MetaModel
|
|
5
5
|
|
6
6
|
include Config::Mixin
|
7
7
|
|
8
|
-
require 'metamodel/model/
|
9
|
-
require 'metamodel/model/
|
10
|
-
require 'metamodel/model/property_constructor'
|
8
|
+
require 'metamodel/model/model'
|
9
|
+
require 'metamodel/model/property'
|
11
10
|
require 'metamodel/command/build/renderer'
|
12
11
|
|
13
12
|
def initialize
|
@@ -35,9 +34,33 @@ module MetaModel
|
|
35
34
|
end
|
36
35
|
|
37
36
|
def define(model_name)
|
38
|
-
|
39
|
-
yield
|
40
|
-
|
37
|
+
@models << Model.new(model_name)
|
38
|
+
yield
|
39
|
+
end
|
40
|
+
|
41
|
+
def attr(key, type = :string, *args)
|
42
|
+
current_model.properties << Property.new(key, type, args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_one(name, model)
|
46
|
+
current_model.relation_properties << Property.new(name, model, :has_one)
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_many(name, model)
|
50
|
+
property = Property.new(name, model, :has_many)
|
51
|
+
raise Informative, "Property type in has_many relation can't be optional" if property.is_optional?
|
52
|
+
current_model.relation_properties << property
|
53
|
+
end
|
54
|
+
|
55
|
+
def belongs_to(name, model)
|
56
|
+
current_model.relation_properties << Property.new(name, model, :belongs_to)
|
57
|
+
current_model.properties << Property.new("#{name}_id".camelize, "Int", :foreign, :default => 0)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def current_model
|
63
|
+
@models.last
|
41
64
|
end
|
42
65
|
end
|
43
66
|
end
|
@@ -20,9 +20,10 @@ module MetaModel
|
|
20
20
|
|
21
21
|
def templates
|
22
22
|
results = []
|
23
|
-
file_paths = %w{file_header attributes json recordable initialize static_methods instance_methods model_query model_relation}
|
23
|
+
# file_paths = %w{file_header attributes json recordable initialize static_methods instance_methods model_query model_relation}
|
24
|
+
file_paths = %w{file_header attributes recordable initialize static_methods instance_methods model_query model_relation foreign_key}
|
24
25
|
file_paths.each do |file_path|
|
25
|
-
template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../../template/#{file_path}.swift
|
26
|
+
template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../../template/#{file_path}.swift"))
|
26
27
|
results << template
|
27
28
|
end
|
28
29
|
results
|
@@ -21,11 +21,12 @@ module MetaModel
|
|
21
21
|
UI.section "Building MetaModel.framework in project" do
|
22
22
|
clone_project
|
23
23
|
parse_template
|
24
|
+
validate_models
|
24
25
|
render_model_files
|
25
26
|
update_initialize_method
|
26
27
|
build_metamodel_framework
|
27
28
|
end
|
28
|
-
UI.notice "Please drag MetaModel.framework into
|
29
|
+
UI.notice "Please drag MetaModel.framework into Embedded Binaries phrase.\n"
|
29
30
|
end
|
30
31
|
|
31
32
|
def clone_project
|
@@ -33,7 +34,7 @@ module MetaModel
|
|
33
34
|
UI.message "Existing project `#{config.metamodel_xcode_project}`"
|
34
35
|
else
|
35
36
|
UI.section "Cloning MetaModel project into `./metamodel` folder" do
|
36
|
-
Git.clone(config.metamodel_template_uri, 'metamodel')
|
37
|
+
Git.clone(config.metamodel_template_uri, 'metamodel', :depth => 1)
|
37
38
|
UI.message "Using `./metamodel/MetaModel.xcodeproj` to build module"
|
38
39
|
end
|
39
40
|
end
|
@@ -44,13 +45,25 @@ module MetaModel
|
|
44
45
|
@models = parser.parse
|
45
46
|
end
|
46
47
|
|
48
|
+
def validate_models
|
49
|
+
existing_types = @models.map { |m| m.properties.map { |property| property.type } }.flatten.uniq
|
50
|
+
unsupported_types = existing_types - supported_types
|
51
|
+
raise Informative, "Unsupported types #{unsupported_types}" unless unsupported_types == []
|
52
|
+
# class_types = supported_types - built_in_types
|
53
|
+
# @models.each do |model|
|
54
|
+
# model.properties do |property|
|
55
|
+
#
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
end
|
59
|
+
|
47
60
|
def render_model_files
|
48
61
|
UI.section "Generating model files" do
|
49
62
|
Renderer.render(@models)
|
50
63
|
end
|
51
64
|
end
|
52
65
|
def update_initialize_method
|
53
|
-
template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../template/metamodel.swift
|
66
|
+
template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../template/metamodel.swift"))
|
54
67
|
result = ErbalT::render_from_hash(template, { :models => @models })
|
55
68
|
model_path = Pathname.new("./metamodel/MetaModel/MetaModel.swift")
|
56
69
|
File.write model_path, result
|
@@ -112,6 +125,20 @@ module MetaModel
|
|
112
125
|
end
|
113
126
|
end
|
114
127
|
|
128
|
+
def built_in_types
|
129
|
+
%w[Int Double String].map do |t|
|
130
|
+
[t, "#{t}?"]
|
131
|
+
end.flatten
|
132
|
+
end
|
133
|
+
|
134
|
+
def supported_types
|
135
|
+
@models.reduce(%w[Int Double String]) { |types, model|
|
136
|
+
types << model.name.to_s
|
137
|
+
}.map { |type|
|
138
|
+
[type, "#{type}?"]
|
139
|
+
}.flatten
|
140
|
+
end
|
141
|
+
|
115
142
|
end
|
116
143
|
end
|
117
144
|
end
|
@@ -32,9 +32,9 @@ module MetaModel
|
|
32
32
|
modelfile = ''
|
33
33
|
modelfile << "metamodel_version '#{VERSION}'\n\n"
|
34
34
|
modelfile << <<-TEMPLATE.strip_heredoc
|
35
|
-
define :#{model} do
|
35
|
+
define :#{model} do
|
36
36
|
# define #{model} model like this
|
37
|
-
#
|
37
|
+
# attr nickname, :string
|
38
38
|
end
|
39
39
|
TEMPLATE
|
40
40
|
modelfile
|
data/lib/metamodel/config.rb
CHANGED
@@ -0,0 +1,104 @@
|
|
1
|
+
module MetaModel
|
2
|
+
|
3
|
+
class Model
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :properties
|
6
|
+
attr_reader :relation_properties
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
@properties = []
|
11
|
+
@relation_properties = []
|
12
|
+
|
13
|
+
validate
|
14
|
+
end
|
15
|
+
|
16
|
+
def properties_exclude_id
|
17
|
+
@properties.select { |property| property.name != :id }
|
18
|
+
end
|
19
|
+
|
20
|
+
def foreign_id
|
21
|
+
"#{name}_id".camelize(:lower)
|
22
|
+
end
|
23
|
+
|
24
|
+
def table_name
|
25
|
+
name.to_s.tableize
|
26
|
+
end
|
27
|
+
|
28
|
+
def relation_name
|
29
|
+
"#{name}Relation"
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_properties
|
33
|
+
all_properties = properties.clone
|
34
|
+
all_properties.push Property.primary_id
|
35
|
+
all_properties
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate
|
39
|
+
property_keys = @properties.map { |property| property.name }
|
40
|
+
|
41
|
+
unless property_keys.include? :id
|
42
|
+
property_id = Property.new(:id, :int, :unique, :default => 0)
|
43
|
+
@properties << property_id
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash_value
|
48
|
+
self.hash.to_s(16)
|
49
|
+
end
|
50
|
+
|
51
|
+
def property_key_value_pairs
|
52
|
+
@properties.map { |property| "#{property.name.to_s}: #{property.name.to_s}" }.join(", ")
|
53
|
+
end
|
54
|
+
|
55
|
+
def property_key_type_pairs
|
56
|
+
key_type_pairs_with_property(@properties, false)
|
57
|
+
end
|
58
|
+
|
59
|
+
def property_exclude_id_key_value_pairs(prefix = true, cast = false)
|
60
|
+
result = ""
|
61
|
+
if cast
|
62
|
+
result = properties_exclude_id.map { |property| "#{property.name.to_s}: #{property.type_without_optional == "Int" ? "Int(#{property.name.to_s})" : property.name.to_s}" }.join(", ")
|
63
|
+
else
|
64
|
+
result = properties_exclude_id.map { |property| "#{property.name.to_s}: #{property.name.to_s}" }.join(", ")
|
65
|
+
end
|
66
|
+
return result unless prefix
|
67
|
+
return result.length > 0 ? ", #{result}" : ""
|
68
|
+
end
|
69
|
+
|
70
|
+
def property_exclude_id_key_type_pairs(prefix = true)
|
71
|
+
key_type_pairs_with_property(properties_exclude_id, prefix)
|
72
|
+
end
|
73
|
+
|
74
|
+
def key_type_pairs_with_property(properties, prefix = true)
|
75
|
+
result = properties.map { |property|
|
76
|
+
has_default_value = property.has_default_value?
|
77
|
+
default_value = property.type_without_optional == "String" ?
|
78
|
+
"\"#{property.default_value}\"" : property.default_value
|
79
|
+
"#{property.name.to_s}: #{property.type.to_s}#{if has_default_value then " = " + "#{default_value}" end}"
|
80
|
+
}.join(", ")
|
81
|
+
return result unless prefix
|
82
|
+
return result.length > 0 ? ", #{result}" : ""
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_table
|
86
|
+
table = "CREATE TABLE #{table_name}"
|
87
|
+
main_sql = @properties.map do |property|
|
88
|
+
result = "#{property.name} #{property.database_type}"
|
89
|
+
result << " PRIMARY KEY" if property.is_primary?
|
90
|
+
result << " UNIQUE" if property.is_unique?
|
91
|
+
result << " DEFAULT #{property.default_value}" if property.has_default_value?
|
92
|
+
result
|
93
|
+
end
|
94
|
+
foreign_sql = @properties.map do |property|
|
95
|
+
next unless property.is_foreign?
|
96
|
+
reference_table_name = property.type.tableize
|
97
|
+
"FOREIGN KEY(#{property.name}) REFERENCES #{reference_table_name}(_id)"
|
98
|
+
end
|
99
|
+
|
100
|
+
table + "(_id INTEGER PRIMARY KEY, #{(main_sql + foreign_sql).compact.join(", ")});"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module MetaModel
|
2
2
|
|
3
|
-
class
|
3
|
+
class Property
|
4
4
|
attr_reader :json_key
|
5
|
-
|
5
|
+
attr_accessor :name
|
6
6
|
attr_reader :type
|
7
7
|
attr_reader :modifiers
|
8
8
|
|
9
9
|
def initialize(json_key, type = :string, *modifiers)
|
10
10
|
@json_key = json_key
|
11
|
-
@
|
11
|
+
@name = json_key.to_s.camelize(:lower).to_sym
|
12
12
|
@type = convert_symbol_to_type type
|
13
13
|
|
14
14
|
@modifiers = {}
|
@@ -20,6 +20,14 @@ module MetaModel
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
class << self
|
24
|
+
def primary_id
|
25
|
+
property = Property.new(:_id, :int, :primary)
|
26
|
+
property.name = :_id
|
27
|
+
property
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
23
31
|
def type_without_optional
|
24
32
|
return type.to_s[0..-2] if type.to_s.end_with? "?"
|
25
33
|
type
|
@@ -40,6 +48,10 @@ module MetaModel
|
|
40
48
|
type_without_optional == "Int" ? "Int64" : type_without_optional
|
41
49
|
end
|
42
50
|
|
51
|
+
def is_array?
|
52
|
+
@type.pluralize == str
|
53
|
+
end
|
54
|
+
|
43
55
|
def is_unique?
|
44
56
|
@modifiers.include? :unique
|
45
57
|
end
|
@@ -48,16 +60,32 @@ module MetaModel
|
|
48
60
|
@modifiers.include? :primary
|
49
61
|
end
|
50
62
|
|
63
|
+
def is_foreign?
|
64
|
+
@modifiers.include? :foreign
|
65
|
+
end
|
66
|
+
|
51
67
|
def is_optional?
|
52
68
|
@type.to_s.end_with? "?"
|
53
69
|
end
|
54
70
|
|
71
|
+
def has_one?
|
72
|
+
@modifiers.include? :has_one
|
73
|
+
end
|
74
|
+
|
75
|
+
def has_many?
|
76
|
+
@modifiers.include? :has_many
|
77
|
+
end
|
78
|
+
|
79
|
+
def belongs_to?
|
80
|
+
@modifiers.include? :belongs_to
|
81
|
+
end
|
82
|
+
|
55
83
|
def has_default_value?
|
56
|
-
|
84
|
+
!!@modifiers[:default]
|
57
85
|
end
|
58
86
|
|
59
87
|
def default_value
|
60
|
-
modifiers[:default]
|
88
|
+
has_default_value? ? modifiers[:default] : ""
|
61
89
|
end
|
62
90
|
|
63
91
|
private
|
@@ -1,10 +1,10 @@
|
|
1
1
|
public struct <%= model.name %> {
|
2
|
-
<% model.properties.each do |property| %><%= """public var #{property.
|
2
|
+
<% model.properties.each do |property| %><%= """public var #{property.name}: #{property.type}""" %>
|
3
3
|
<% end %>
|
4
4
|
static let tableName = "<%= model.table_name %>"
|
5
5
|
|
6
6
|
public enum Column: String, Unwrapped {
|
7
|
-
<% model.properties.each do |property| %><%= """case #{property.
|
7
|
+
<% model.properties.each do |property| %><%= """case #{property.name} = \"#{property.name}\"""" %>
|
8
8
|
<% end %>
|
9
9
|
var unwrapped: String { get { return self.rawValue.unwrapped } }
|
10
10
|
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<% model.relation_properties.each do |property| %><% if property.has_many? %>
|
2
|
+
<%= """public extension #{model.name} {
|
3
|
+
func append#{property.type}(element: #{property.type}) {
|
4
|
+
var element = element
|
5
|
+
element.update(#{model.foreign_id}: id)
|
6
|
+
}
|
7
|
+
|
8
|
+
func create#{property.type}(id: Int, content: String) -> #{property.type}? {
|
9
|
+
return #{property.type}.create(id, content: content, #{model.foreign_id}: id)
|
10
|
+
}
|
11
|
+
|
12
|
+
func delete#{property.type}(id: Int) {
|
13
|
+
#{property.type}.filter(.#{model.foreign_id}, value: id).findBy(id: id).first?.delete()
|
14
|
+
}
|
15
|
+
var #{property.name}: [#{property.type}] {
|
16
|
+
get {
|
17
|
+
return #{property.type}.filter(.id, value: id).result
|
18
|
+
}
|
19
|
+
set {
|
20
|
+
#{property.name}.forEach { (element) in
|
21
|
+
var element = element
|
22
|
+
element.update(#{model.foreign_id}: 0)
|
23
|
+
}
|
24
|
+
newValue.forEach { (element) in
|
25
|
+
var element = element
|
26
|
+
element.update(#{model.foreign_id}: id)
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}""" %><% elsif property.belongs_to? %>
|
31
|
+
<%= """public extension #{model.name} {
|
32
|
+
var #{property.name}: #{property.type}? {
|
33
|
+
get {
|
34
|
+
return #{property.type}.find(id)
|
35
|
+
}
|
36
|
+
set {
|
37
|
+
guard let newValue = newValue else { return }
|
38
|
+
update(#{property.type.camelize(:lower)}Id: newValue.id)
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
}""" %><% elsif property.has_one? %>
|
43
|
+
<%= """public extension #{model.name} {
|
44
|
+
var #{property.name}: #{property.type}? {
|
45
|
+
get {
|
46
|
+
return #{property.type}.find(id)
|
47
|
+
}
|
48
|
+
set {
|
49
|
+
#{property.type}.filter(.#{model.name.to_s.camelize(:lower)}Id, value: id).deleteAll
|
50
|
+
guard var newValue = newValue else { return }
|
51
|
+
newValue.update(articleId: id)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}"""%><% end %><% end %>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
public extension <%= model.name %> {
|
2
|
+
var itself: String { get { return "WHERE \(<%= model.name %>.tableName.unwrapped).\("id".unwrapped) = \(id)" } }
|
3
|
+
|
4
|
+
var delete: Bool {
|
5
|
+
get {
|
6
|
+
let deleteSQL = "DELETE FROM \(<%= model.name %>.tableName.unwrapped) \(itself)"
|
7
|
+
executeSQL(deleteSQL)
|
8
|
+
return true
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
<% model.properties_exclude_id.each do |property| %><%= """mutating func update(#{property.name} #{property.name}: #{property.type}) -> #{model.name} {
|
13
|
+
return self.update([.#{property.name}: #{property.name}])
|
14
|
+
}""" %>
|
15
|
+
<% end %>
|
16
|
+
mutating func update(attributes: [<%= model.name %>.Column: Any]) -> <%= model.name %> {
|
17
|
+
var setSQL: [String] = []
|
18
|
+
if let attributes = attributes as? [<%= model.name %>.Column: Unwrapped] {
|
19
|
+
for (key, value) in attributes {
|
20
|
+
switch key {
|
21
|
+
<% model.properties_exclude_id.each do |property| %><%= """case .#{property.name}: setSQL.append(\"\\(key.unwrapped) = \\(value.unwrapped)\")""" %>
|
22
|
+
<% end %>default: break
|
23
|
+
}
|
24
|
+
}
|
25
|
+
let updateSQL = "UPDATE \(<%= model.name %>.tableName.unwrapped) SET \(setSQL.joinWithSeparator(", ")) \(itself)"
|
26
|
+
executeSQL(updateSQL) {
|
27
|
+
for (key, value) in attributes {
|
28
|
+
switch key {
|
29
|
+
<% model.properties_exclude_id.each do |property| %><%= """case .#{property.name}: self.#{property.name} = value as#{property.is_optional? ? "?" : "!"} #{property.type_without_optional}""" %>
|
30
|
+
<% end %>default: break
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
return self
|
36
|
+
}
|
37
|
+
var save: <%= model.name %> {
|
38
|
+
mutating get {
|
39
|
+
if let _ = <%= model.name %>.find(id) {
|
40
|
+
update([<% column_values = model.properties.map do |property| %><% ".#{property.name}: #{property.name}" %><% end %><%= column_values.join(", ") %>])
|
41
|
+
} else {
|
42
|
+
<%= model.name %>.create(id<%= model.property_exclude_id_key_value_pairs %>)
|
43
|
+
}
|
44
|
+
return self
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
@@ -2,17 +2,13 @@ extension <%= model.name %> {
|
|
2
2
|
public static func parse(json: [String: AnyObject]) -> <%= model.name %> {
|
3
3
|
let id: Int = json["id"] as! Int
|
4
4
|
<% model.properties_exclude_id.each do |property| %>
|
5
|
-
<%= """let #{property.
|
5
|
+
<%= """let #{property.name}: #{property.type} = json[\"#{property.name}\"] as! #{property.type}""" %>
|
6
6
|
<% end %>
|
7
7
|
return <%= model.name %>(<%= model.property_key_value_pairs %>)
|
8
8
|
}
|
9
9
|
|
10
10
|
public static func parse(jsons: [[String: AnyObject]]) -> [<%= model.name %>] {
|
11
|
-
|
12
|
-
for json in jsons {
|
13
|
-
results.append(<%= model.name %>.parse(json))
|
14
|
-
}
|
15
|
-
return results
|
11
|
+
return jsons.map(<%= model.name %>.parse)
|
16
12
|
}
|
17
13
|
|
18
14
|
public static func parse(data: NSData) throws -> <%= model.name %> {
|
@@ -31,17 +31,21 @@ public class MetaModel {
|
|
31
31
|
}
|
32
32
|
}
|
33
33
|
|
34
|
-
func executeSQL(sql: String,
|
35
|
-
|
36
|
-
|
34
|
+
func executeSQL(sql: String, verbose: Bool = true, success: (() -> ())? = nil) -> Statement? {
|
35
|
+
if verbose {
|
36
|
+
print("-> Begin Transaction")
|
37
|
+
}
|
37
38
|
let startDate = NSDate()
|
38
39
|
do {
|
39
40
|
let result = try db.run(sql)
|
40
41
|
let endDate = NSDate()
|
41
42
|
let interval = endDate.timeIntervalSinceDate(startDate) * 1000
|
42
|
-
print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
|
43
|
-
print("-> Commit Transaction")
|
44
43
|
|
44
|
+
if verbose {
|
45
|
+
print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
|
46
|
+
print("-> Commit Transaction")
|
47
|
+
print("\n")
|
48
|
+
}
|
45
49
|
if let success = success {
|
46
50
|
success()
|
47
51
|
}
|
@@ -50,22 +54,29 @@ func executeSQL(sql: String, silent: Bool = false, success: (() -> ())? = nil) -
|
|
50
54
|
} catch let error {
|
51
55
|
let endDate = NSDate()
|
52
56
|
let interval = endDate.timeIntervalSinceDate(startDate) * 1000
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
if verbose {
|
58
|
+
print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
|
59
|
+
print("\t\(error)")
|
60
|
+
print("-> Rollback transaction")
|
61
|
+
print("\n")
|
62
|
+
}
|
56
63
|
}
|
57
64
|
return nil
|
58
65
|
}
|
59
66
|
|
60
|
-
func executeScalarSQL(sql: String,
|
61
|
-
|
62
|
-
|
67
|
+
func executeScalarSQL(sql: String, verbose: Bool = false, success: (() -> ())? = nil) -> Binding? {
|
68
|
+
if verbose {
|
69
|
+
print("-> Begin Transaction")
|
70
|
+
}
|
63
71
|
let startDate = NSDate()
|
64
72
|
let result = db.scalar(sql)
|
65
73
|
let endDate = NSDate()
|
66
74
|
let interval = endDate.timeIntervalSinceDate(startDate) * 1000
|
67
|
-
|
68
|
-
|
75
|
+
if verbose {
|
76
|
+
print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
|
77
|
+
print("-> Commit Transaction")
|
78
|
+
print("\n")
|
79
|
+
}
|
69
80
|
|
70
81
|
if let success = success {
|
71
82
|
success()
|
@@ -19,10 +19,10 @@ public extension <%= model.name %> {
|
|
19
19
|
return <%= model.relation_name %>().findBy(id: id).first
|
20
20
|
}
|
21
21
|
|
22
|
-
<% model.properties_exclude_id.each do |property| %><%= """static func findBy(#{property.
|
23
|
-
return #{model.relation_name}().findBy(#{property.
|
24
|
-
}
|
25
|
-
|
22
|
+
<% model.properties_exclude_id.each do |property| %><%= """static func findBy(#{property.name} #{property.name}: #{property.type_without_optional}) -\> #{model.name}? {
|
23
|
+
return #{model.relation_name}().findBy(#{property.name}: #{property.name}).first
|
24
|
+
}
|
25
|
+
""" %><% end %>
|
26
26
|
static func filter(column: <%= model.name %>.Column, value: Any) -> <%= model.relation_name %> {
|
27
27
|
return <%= model.relation_name %>().filter([column: value])
|
28
28
|
}
|
@@ -19,8 +19,8 @@ public class <%= model.relation_name %>: Relation<<%= model.name %>> {
|
|
19
19
|
}
|
20
20
|
|
21
21
|
<% model.properties_exclude_id.each do |property| %>
|
22
|
-
<%= """public func findBy(#{property.
|
23
|
-
return self.filter([.#{property.
|
22
|
+
<%= """public func findBy(#{property.name} #{property.name}: #{property.type_without_optional}) -\> Self {
|
23
|
+
return self.filter([.#{property.name}: #{property.name}])
|
24
24
|
}""" %>
|
25
25
|
<% end %>
|
26
26
|
|
@@ -79,4 +79,17 @@ public class <%= model.relation_name %>: Relation<<%= model.name %>> {
|
|
79
79
|
return self
|
80
80
|
}
|
81
81
|
|
82
|
+
public func updateAll(column: <%= model.name %>.Column, value: Any) {
|
83
|
+
self.result.forEach { (element) in
|
84
|
+
var element = element
|
85
|
+
element.update([column: value])
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
public var deleteAll: Bool {
|
90
|
+
get {
|
91
|
+
self.result.forEach { $0.delete }
|
92
|
+
return true
|
93
|
+
}
|
94
|
+
}
|
82
95
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
extension <%= model.name %>: Recordable {
|
2
2
|
public init(values: Array<Optional<Binding>>) {
|
3
|
-
<% model.properties.each_with_index do |property, index| %><%= """let #{property.
|
3
|
+
<% model.properties.each_with_index do |property, index| %><%= """let #{property.name}: #{property.real_type} = values[#{index+1}] as! #{property.real_type}""" %>
|
4
4
|
<% end %>
|
5
5
|
self.init(id: Int(id)<%= model.property_exclude_id_key_value_pairs(true, true) %>)
|
6
6
|
}
|
@@ -9,23 +9,25 @@ public extension <%= model.name %> {
|
|
9
9
|
return Int(count)
|
10
10
|
}
|
11
11
|
|
12
|
-
static func new(<%= model.
|
13
|
-
return <%= model.name %>(
|
12
|
+
static func new(<%= model.property_key_type_pairs %>) -> <%= model.name %> {
|
13
|
+
return <%= model.name %>(<%= model.property_key_value_pairs %>)
|
14
14
|
}
|
15
15
|
|
16
16
|
static func create(<%= model.property_key_type_pairs %>) -> <%= model.name %>? {
|
17
|
+
if <%= model.properties.select { |p| p.name.to_s.downcase.end_with? "id" }.map { |p| "#{p.name} == 0" }.join(" || ") %> { return nil }
|
18
|
+
|
17
19
|
var columnsSQL: [<%= model.name %>.Column] = []
|
18
20
|
var valuesSQL: [Unwrapped] = []
|
19
21
|
|
20
22
|
columnsSQL.append(.id)
|
21
23
|
valuesSQL.append(id)
|
22
24
|
<% model.properties_exclude_id.each do |property| %><% if property.is_optional? %>
|
23
|
-
<%= """if let #{property.
|
24
|
-
columnsSQL.append(.#{property.
|
25
|
-
valuesSQL.append(#{property.
|
25
|
+
<%= """if let #{property.name} = #{property.name} {
|
26
|
+
columnsSQL.append(.#{property.name})
|
27
|
+
valuesSQL.append(#{property.name})
|
26
28
|
}""" %><% else %>
|
27
|
-
<%= """columnsSQL.append(.#{property.
|
28
|
-
valuesSQL.append(#{property.
|
29
|
+
<%= """columnsSQL.append(.#{property.name})
|
30
|
+
valuesSQL.append(#{property.name})
|
29
31
|
""" %><% end %><% end %>
|
30
32
|
|
31
33
|
let insertSQL = "INSERT INTO \(tableName.unwrapped) (\(columnsSQL.map { $0.rawValue }.joinWithSeparator(", "))) VALUES (\(valuesSQL.map { $0.unwrapped }.joinWithSeparator(", ")))"
|
data/lib/metamodel/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metamodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Draveness Zuo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: claide
|
@@ -148,19 +148,19 @@ files:
|
|
148
148
|
- lib/metamodel/command/generate.rb
|
149
149
|
- lib/metamodel/command/init.rb
|
150
150
|
- lib/metamodel/config.rb
|
151
|
-
- lib/metamodel/model/
|
152
|
-
- lib/metamodel/model/
|
153
|
-
- lib/metamodel/
|
154
|
-
- lib/metamodel/template/
|
155
|
-
- lib/metamodel/template/
|
156
|
-
- lib/metamodel/template/initialize.swift
|
157
|
-
- lib/metamodel/template/instance_methods.swift
|
158
|
-
- lib/metamodel/template/json.swift
|
159
|
-
- lib/metamodel/template/metamodel.swift
|
160
|
-
- lib/metamodel/template/model_query.swift
|
161
|
-
- lib/metamodel/template/model_relation.swift
|
162
|
-
- lib/metamodel/template/recordable.swift
|
163
|
-
- lib/metamodel/template/static_methods.swift
|
151
|
+
- lib/metamodel/model/model.rb
|
152
|
+
- lib/metamodel/model/property.rb
|
153
|
+
- lib/metamodel/template/attributes.swift
|
154
|
+
- lib/metamodel/template/file_header.swift
|
155
|
+
- lib/metamodel/template/foreign_key.swift
|
156
|
+
- lib/metamodel/template/initialize.swift
|
157
|
+
- lib/metamodel/template/instance_methods.swift
|
158
|
+
- lib/metamodel/template/json.swift
|
159
|
+
- lib/metamodel/template/metamodel.swift
|
160
|
+
- lib/metamodel/template/model_query.swift
|
161
|
+
- lib/metamodel/template/model_relation.swift
|
162
|
+
- lib/metamodel/template/recordable.swift
|
163
|
+
- lib/metamodel/template/static_methods.swift
|
164
164
|
- lib/metamodel/user_interface.rb
|
165
165
|
- lib/metamodel/version.rb
|
166
166
|
homepage: https://github.com/MModel/MetaModel
|
@@ -183,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
requirements: []
|
185
185
|
rubyforge_project:
|
186
|
-
rubygems_version: 2.6.
|
186
|
+
rubygems_version: 2.6.4
|
187
187
|
signing_key:
|
188
188
|
specification_version: 4
|
189
189
|
summary: The Cocoa models generator.
|
@@ -1,79 +0,0 @@
|
|
1
|
-
module MetaModel
|
2
|
-
|
3
|
-
class CocoaModel
|
4
|
-
attr_reader :name
|
5
|
-
attr_reader :properties
|
6
|
-
|
7
|
-
def initialize(name)
|
8
|
-
@name = name
|
9
|
-
@properties = []
|
10
|
-
|
11
|
-
validate
|
12
|
-
end
|
13
|
-
|
14
|
-
def properties_exclude_id
|
15
|
-
@properties.select { |property| property.key != :id }
|
16
|
-
end
|
17
|
-
|
18
|
-
def table_name
|
19
|
-
name.to_s.tableize
|
20
|
-
end
|
21
|
-
|
22
|
-
def relation_name
|
23
|
-
"#{name}Relation"
|
24
|
-
end
|
25
|
-
|
26
|
-
def validate
|
27
|
-
property_keys = @properties.map { |property| property.key }
|
28
|
-
|
29
|
-
unless property_keys.include? :id
|
30
|
-
property_id = CocoaProperty.new(:id, :int, :primary)
|
31
|
-
@properties << property_id
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def hash_value
|
36
|
-
self.hash.to_s(16)
|
37
|
-
end
|
38
|
-
|
39
|
-
def property_key_value_pairs
|
40
|
-
@properties.map { |property| "#{property.key.to_s}: #{property.key.to_s}" }.join(", ")
|
41
|
-
end
|
42
|
-
|
43
|
-
def property_key_type_pairs
|
44
|
-
@properties.map { |property| "#{property.key.to_s}: #{property.type.to_s}" }.join(", ")
|
45
|
-
end
|
46
|
-
|
47
|
-
def property_exclude_id_key_value_pairs(prefix = true, cast = false)
|
48
|
-
result = ""
|
49
|
-
if cast
|
50
|
-
result = properties_exclude_id.map { |property| "#{property.key.to_s}: #{property.type_without_optional == "Int" ? "Int(#{property.key.to_s})" : property.key.to_s}" }.join(", ")
|
51
|
-
else
|
52
|
-
result = properties_exclude_id.map { |property| "#{property.key.to_s}: #{property.key.to_s}" }.join(", ")
|
53
|
-
end
|
54
|
-
return result unless prefix
|
55
|
-
return result.length > 0 ? ", #{result}" : ""
|
56
|
-
end
|
57
|
-
|
58
|
-
def property_exclude_id_key_type_pairs(prefix = true)
|
59
|
-
result = properties_exclude_id.map { |property| "#{property.key.to_s}: #{property.type.to_s}" }.join(", ")
|
60
|
-
return result unless prefix
|
61
|
-
return result.length > 0 ? ", #{result}" : ""
|
62
|
-
end
|
63
|
-
|
64
|
-
def build_table
|
65
|
-
table = "CREATE TABLE #{table_name}"
|
66
|
-
main_sql = @properties.map do |property|
|
67
|
-
result = "#{property.key} #{property.database_type}"
|
68
|
-
result << " NOT NULL" if !property.is_optional?
|
69
|
-
result << " PRIMARY KEY" if property.is_primary?
|
70
|
-
result << " UNIQUE" if property.is_unique?
|
71
|
-
result << " DEFAULT #{property.default_value}" if property.has_default_value?
|
72
|
-
result
|
73
|
-
end.join(", ")
|
74
|
-
main_sql = "(#{main_sql});"
|
75
|
-
table + main_sql
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module MetaModel
|
2
|
-
|
3
|
-
class PropertyConstructor
|
4
|
-
|
5
|
-
attr_reader :model
|
6
|
-
|
7
|
-
def initialize(model)
|
8
|
-
@model = model
|
9
|
-
end
|
10
|
-
|
11
|
-
def method_missing(meth, *arguments, &block)
|
12
|
-
(class << self; self; end).class_eval do
|
13
|
-
define_method meth do |type, *arguments|
|
14
|
-
save_property CocoaProperty.new(meth, type, arguments)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
self.send meth, *arguments
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
# Save property to current Cocoa Model
|
23
|
-
#
|
24
|
-
# @param [CocoaProperty] the instance for cocoa property
|
25
|
-
# @return [Void]
|
26
|
-
def save_property(property)
|
27
|
-
@model.properties << property
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
public extension <%= model.name %> {
|
2
|
-
var itself: String { get { return "WHERE \(<%= model.name %>.tableName.unwrapped).\("id".unwrapped) = \(id)" } }
|
3
|
-
|
4
|
-
func delete() {
|
5
|
-
let deleteSQL = "DELETE FROM \(<%= model.name %>.tableName.unwrapped) \(itself)"
|
6
|
-
executeSQL(deleteSQL)
|
7
|
-
}
|
8
|
-
|
9
|
-
<% model.properties_exclude_id.each do |property| %><%= """mutating func update(#{property.key} #{property.key}: #{property.type}) -> #{model.name} {
|
10
|
-
return self.update([.#{property.key}: #{property.key}])
|
11
|
-
}""" %>
|
12
|
-
<% end %>
|
13
|
-
mutating func update(attributes: [<%= model.name %>.Column: Any]) -> <%= model.name %> {
|
14
|
-
var setSQL: [String] = []
|
15
|
-
for (key, _) in attributes {
|
16
|
-
switch key {
|
17
|
-
<% model.properties_exclude_id.each do |property| %><%= """case .#{property.key}: setSQL.append(\"\\(key.unwrapped) = \\(#{property.key}#{property.is_optional? ? "?" : ""}.unwrapped)\")""" %>
|
18
|
-
<% end %>default: break
|
19
|
-
}
|
20
|
-
}
|
21
|
-
let updateSQL = "UPDATE \(<%= model.name %>.tableName.unwrapped) SET \(setSQL.joinWithSeparator(", ")) \(itself)"
|
22
|
-
executeSQL(updateSQL) {
|
23
|
-
for (key, value) in attributes {
|
24
|
-
switch key {
|
25
|
-
<% model.properties_exclude_id.each do |property| %><%= """case .#{property.key}: self.#{property.key} = value as#{property.is_optional? ? "?" : "!"} #{property.type_without_optional}""" %>
|
26
|
-
<% end %>default: break
|
27
|
-
}
|
28
|
-
}
|
29
|
-
}
|
30
|
-
return self
|
31
|
-
}
|
32
|
-
var save: <%= model.name %> {
|
33
|
-
get {
|
34
|
-
<%= model.name %>.create(id<%= model.property_exclude_id_key_value_pairs %>)
|
35
|
-
return self
|
36
|
-
}
|
37
|
-
}
|
38
|
-
}
|
File without changes
|
File without changes
|