metamodel 0.0.5 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/draveness/metamodel/blob/master/LICENSE)
|
6
6
|
[![Gem](https://img.shields.io/gem/v/metamodel.svg?style=flat)](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
|
![integrate-metamodel-framework](images/integrate-metamodel-framework.png)
|
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
|