metamodel 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0039698aeb5a6943fbab150f42314e52fb601203
4
- data.tar.gz: a811eaa4d44154902463572ed3854c0f956b77e7
3
+ metadata.gz: 7736cf1e138517c6079cfc3c290f943ad285bbee
4
+ data.tar.gz: 75cc11f484c32d1a54ef70d457ba9d83a89f75d0
5
5
  SHA512:
6
- metadata.gz: 3d73ffe24665ff900cabcf2c8ba7a72708fe3acc2061db5e7b898ac21488e1d6e2b2418b8d705c97e2cebda43bb7f399823aeeadf73bd96b4f436df3b4020b7d
7
- data.tar.gz: 2c73680883d69b487d845cee94a8c07258006c4a87deb39ad768dcac83096b894ca2643bf4b3dc24b0c095531a9260870f4a8152f9d6651028c73dad9039e735
6
+ metadata.gz: dbad5e08fb83943368a289a2bdf7602b20297a7267f5bcabc5ada3f9264b0ee8a1d8c19e0ee6c5fdc5034094897000486a1b0e3ddcbf8eaa2e304c36d326b2fd
7
+ data.tar.gz: 0359d81ec9bcd81b30fa7ae9d7056fc7214dde6ed7b8e57dccba885a7195113f7671f8db6aa791602f7818168d28a846d2b271761a50a130915f818a4dbcbc18
data/README.md CHANGED
@@ -2,3 +2,118 @@
2
2
 
3
3
  # MetaModel
4
4
 
5
+ [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/draveness/metamodel/blob/master/LICENSE)
6
+ [![Gem](https://img.shields.io/gem/v/metamodel.svg?style=flat)](http://rubygems.org/gems/metamodel)
7
+
8
+ MetaModel is an iOS framework that includes everything about model layer, data persistent, JSON to model constructor and a bunch of APIs which provides a way of dealing with client side database very easily.
9
+
10
+ > MetaModel is under-development, API may constantly change before gets to 1.0.0.
11
+
12
+ + [x] Fastest JSON to model API
13
+ + [x] Dealing with database without writing SQL
14
+ + [x] Most concise API to retrieve data from persistent level
15
+
16
+ Use a scaffold file to define your model:
17
+
18
+ ```ruby
19
+ metamodel_version '0.0.1'
20
+
21
+ define :User do |j|
22
+ # define User model like this
23
+ j.nickname :string
24
+ j.avatar :string
25
+ j.email :string, :unique, default: "default@gmail.com"
26
+ end
27
+ ```
28
+
29
+ And then run `meta build` will automatically generate all the code you need.
30
+
31
+ ## Installation
32
+
33
+ ```
34
+ sudo gem install metamodel --verbose
35
+ ```
36
+
37
+ **System Requirements**: Current version of MetaModel requires macOS with Ruby 2.2.2 or above
38
+
39
+ ## Quick Start
40
+
41
+ After installation , run `meta init` in your iOS project root folder which will make a `scaffold` directory in current folder.
42
+
43
+ ```shell
44
+ $ cd /path/to/project
45
+ $ meta init
46
+
47
+ Initialing MetaModel project
48
+
49
+ Creating `scaffold` folder for MetaModel
50
+ ```
51
+
52
+ Generate your model scaffold file with `meta generate`.
53
+
54
+ ```shell
55
+ $ meta generate User
56
+
57
+ Generating model scaffold file
58
+
59
+ -> Adding `user.rb` to scaffold folder
60
+
61
+ [!] `user.rb` has already generated, use the command below to edit it.
62
+
63
+ vim scaffold/user.rb
64
+ ```
65
+
66
+ Edit scaffold file using vim, Emacs or other editor and run `meta build`.
67
+
68
+ ```shell
69
+ $ meta build
70
+
71
+ Building MetaModel project
72
+
73
+ Cloning MetaModel project into `./MetaModel` folder
74
+ Using `./MetaModel/MetaModel.xcodeproj` to build module
75
+
76
+ Analyzing scaffold files
77
+ -> Resolving `user.rb`
78
+
79
+ Generating model files
80
+ -> Using User.swift file
81
+ ```
82
+
83
+ This command create a brand new xcode project in `./MetaModel` folder, just add the `MetaModel.project` into your project or workspace. And add `MetaModel.framework` to **Linked frameworks and Libraries** phrase which located in `General` tab.
84
+
85
+ ![add-metamodel-project-demo](images/add-metamodel-project-demo.png)
86
+
87
+ Add this line of code in your project.
88
+
89
+ ```swift
90
+ import MetaModel
91
+ ```
92
+
93
+ ![import-metamodel-module](images/import-metamodel-module.png)
94
+
95
+ ## License
96
+
97
+ This project is licensed under the terms of the MIT license. See the [LICENSE](./LICENSE) file.
98
+
99
+ The MIT License (MIT)
100
+
101
+ Copyright (c) 2016 Draveness
102
+
103
+ Permission is hereby granted, free of charge, to any person obtaining a copy
104
+ of this software and associated documentation files (the "Software"), to deal
105
+ in the Software without restriction, including without limitation the rights
106
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107
+ copies of the Software, and to permit persons to whom the Software is
108
+ furnished to do so, subject to the following conditions:
109
+
110
+ The above copyright notice and this permission notice shall be included in all
111
+ copies or substantial portions of the Software.
112
+
113
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
114
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
115
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
116
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
119
+ SOFTWARE.
@@ -15,15 +15,13 @@ module MetaModel
15
15
  end
16
16
 
17
17
  def parse
18
- title_options = { :verbose_prefix => '-> '.green }
19
18
  UI.section "Analyzing scaffold files" do
20
19
  scaffold_path = config.scaffold_path
21
20
  scaffolds = Dir[scaffold_path + "*.rb"]
22
21
  scaffolds.each do |scaffold_file|
23
- UI.titled_section "Resolving `#{File.basename(scaffold_file)}`", title_options do
24
- scaffold_code = File.read(scaffold_path + scaffold_file)
25
- eval scaffold_code
26
- end
22
+ UI.message '-> '.green + "Resolving `#{File.basename(scaffold_file)}`"
23
+ scaffold_code = File.read(scaffold_path + scaffold_file)
24
+ eval scaffold_code
27
25
  end
28
26
  end
29
27
  @models
@@ -38,9 +36,7 @@ module MetaModel
38
36
 
39
37
  def define(model_name)
40
38
  model = CocoaModel.new(model_name)
41
-
42
39
  yield PropertyConstructor.new(model)
43
-
44
40
  @models << model
45
41
  end
46
42
  end
@@ -17,29 +17,44 @@ module MetaModel
17
17
  end
18
18
 
19
19
  class << self
20
- def render(model)
21
- template_path = File.expand_path(File.join(File.dirname(__FILE__), "../../template/model.swift.erb"))
22
- template = File.read template_path
23
20
 
24
- result = ErbalT::render_from_hash(template, { :model => model })
25
- model_path = Pathname.new("./MetaModel/MetaModel/#{model.name}.swift")
26
- File.write model_path, result
21
+ def templates
22
+ results = []
23
+ file_paths = %w{file_header attributes json recordable initialize static_methods instance_methods model_query model_relation}
24
+ file_paths.each do |file_path|
25
+ template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../../template/#{file_path}.swift.erb"))
26
+ results << template
27
+ end
28
+ results
29
+ end
27
30
 
31
+ def render(models)
28
32
  project = Xcodeproj::Project.open(Config.instance.metamodel_xcode_project)
29
33
  target = project.targets.first
30
-
31
- target.source_build_phase.files_references.each do |file_ref|
32
- target.source_build_phase.remove_file_reference(file_ref) if file_ref && "#{model.name}.swift" == file_ref.name
34
+ models.each do |model|
35
+ target.source_build_phase.files_references.each do |file_ref|
36
+ target.source_build_phase.remove_file_reference(file_ref) if file_ref && "#{model.name}.swift" == file_ref.name
37
+ end
33
38
  end
34
-
35
39
  models_group = project.main_group.find_subpath('MetaModel/Models', true)
36
40
  models_group.clear
37
41
  models_group.set_source_tree('SOURCE_ROOT')
38
- file_ref = models_group.new_reference Pathname.new("MetaModel/#{model.name}.swift")
39
- target.add_file_references [file_ref]
40
42
 
41
- project.save
43
+ file_refs = []
44
+ models.each do |model|
45
+ result = templates.map { |template|
46
+ ErbalT::render_from_hash(template, { :model => model })
47
+ }.join("\n")
48
+ model_path = Pathname.new("./MetaModel/MetaModel/#{model.name}.swift")
49
+ File.write model_path, result
42
50
 
51
+ file_refs << models_group.new_reference(Pathname.new("MetaModel/#{model.name}.swift"))
52
+
53
+ UI.message '-> '.green + "Using #{model.name}.swift file"
54
+ end
55
+ target.add_file_references file_refs
56
+
57
+ project.save
43
58
  end
44
59
  end
45
60
 
@@ -22,6 +22,7 @@ module MetaModel
22
22
  clone_project
23
23
  parse_template
24
24
  render_model_files
25
+ update_initialize_method
25
26
  end
26
27
  end
27
28
 
@@ -42,22 +43,35 @@ module MetaModel
42
43
  end
43
44
 
44
45
  def render_model_files
45
- title_options = { :verbose_prefix => '-> '.green }
46
46
  UI.section "Generating model files" do
47
- @models.each do |model|
48
- UI.titled_section "Using #{model.name}.swift file", title_options do
49
- Renderer.render(model)
50
- end
51
- end
47
+ Renderer.render(@models)
52
48
  end
53
49
  end
54
50
 
51
+ def update_initialize_method
52
+ template = File.read File.expand_path(File.join(File.dirname(__FILE__), "../template/metamodel.swift.erb"))
53
+ result = ErbalT::render_from_hash(template, { :models => @models })
54
+ model_path = Pathname.new("./MetaModel/MetaModel/MetaModel.swift")
55
+ File.write model_path, result
56
+ end
57
+
55
58
  def validate!
56
59
  super
57
60
  raise Informative, 'No scaffold folder in directory' unless config.scaffold_path_in_dir(Pathname.pwd)
58
61
  end
59
62
 
60
63
  private
64
+
65
+ class ErbalT < OpenStruct
66
+ def self.render_from_hash(t, h)
67
+ ErbalT.new(h).render(t)
68
+ end
69
+
70
+ def render(template)
71
+ ERB.new(template).result(binding)
72
+ end
73
+ end
74
+
61
75
  end
62
76
  end
63
77
  end
@@ -20,7 +20,7 @@ module MetaModel
20
20
  end
21
21
 
22
22
  def run
23
- UI.section "Initiating MetaModel project" do
23
+ UI.section "Initialing MetaModel project" do
24
24
  UI.section "Creating `scaffold` folder for MetaModel" do
25
25
  FileUtils.mkdir(@scaffold_path)
26
26
  end
@@ -66,7 +66,7 @@ module MetaModel
66
66
  # @return [String]
67
67
  #
68
68
  def metamodel_template_uri
69
- "git@github.com:Draveness/MetaModel-Template.git"
69
+ "git@github.com:MetaModel-Framework/MetaModel-Template.git"
70
70
  end
71
71
 
72
72
  # Returns the path of the MetaModel.xcodeproj.
@@ -16,7 +16,7 @@ module MetaModel
16
16
  end
17
17
 
18
18
  def table_name
19
- name.to_s.pluralize.underscore
19
+ name.to_s.tableize
20
20
  end
21
21
 
22
22
  def relation_name
@@ -32,24 +32,38 @@ module MetaModel
32
32
  end
33
33
  end
34
34
 
35
+ def property_key_value_pairs
36
+ @properties.map { |property| "#{property.key.to_s}: #{property.key.to_s}" }.join(", ")
37
+ end
38
+
39
+ def property_key_type_pairs
40
+ @properties.map { |property| "#{property.key.to_s}: #{property.type.to_s}" }.join(", ")
41
+ end
42
+
43
+ def property_exclude_id_key_value_pairs(prefix = true)
44
+ result = properties_exclude_id.map { |property| "#{property.key.to_s}: #{property.key.to_s}" }.join(", ")
45
+ return result unless prefix
46
+ return result.length > 0 ? ", #{result}" : ""
47
+ end
48
+
49
+ def property_exclude_id_key_type_pairs(prefix = true)
50
+ result = properties_exclude_id.map { |property| "#{property.key.to_s}: #{property.type.to_s}" }.join(", ")
51
+ return result unless prefix
52
+ return result.length > 0 ? ", #{result}" : ""
53
+ end
54
+
35
55
  def build_table
36
- table = ""
37
- @properties.each do |property|
38
- property_key = property.key
39
- if property.has_default_value?
40
- default_value = property.default_value
41
- if default_value.is_a? String
42
- table << "t.column(#{property_key}, defaultValue: \"#{default_value}\")\n\t\t\t"
43
- else
44
- table << "t.column(#{property_key}, defaultValue: #{default_value})\n\t\t\t"
45
- end
46
- else
47
- table << "t.column(#{property_key})\n\t\t\t"
48
- end
49
- table << "t.primaryKey(#{property_key})\n\t\t\t" if property.is_primary?
50
- table << "t.unique(#{property_key})\n\t\t\t" if property.is_unique?
51
- end
52
- table
56
+ table = "CREATE TABLE #{table_name}"
57
+ main_sql = @properties.map do |property|
58
+ result = "#{property.key} #{property.database_type}"
59
+ result << " NOT NULL" if !property.is_optional?
60
+ result << " PRIMARY KEY" if property.is_primary?
61
+ result << " UNIQUE" if property.is_unique?
62
+ result << " DEFAULT #{property.default_value}" if property.has_default_value?
63
+ result
64
+ end.join(", ")
65
+ main_sql = "(#{main_sql});"
66
+ table + main_sql
53
67
  end
54
68
  end
55
69
 
@@ -20,6 +20,22 @@ module MetaModel
20
20
  end
21
21
  end
22
22
 
23
+ def type_without_optional
24
+ return type.to_s[0..-2] if key.to_s.end_with? "?"
25
+ type
26
+ end
27
+
28
+ def database_type
29
+ lowercase_type = self.type.downcase
30
+ if lowercase_type == "string"
31
+ return "TEXT"
32
+ elsif lowercase_type == "int"
33
+ return "INTEGER"
34
+ elsif lowercase_type == "double"
35
+ return "REAL"
36
+ end
37
+ end
38
+
23
39
  def is_unique?
24
40
  @modifiers.include? :unique
25
41
  end
@@ -28,6 +44,10 @@ module MetaModel
28
44
  @modifiers.include? :primary
29
45
  end
30
46
 
47
+ def is_optional?
48
+ @type.to_s.end_with? "?"
49
+ end
50
+
31
51
  def has_default_value?
32
52
  @modifiers[:default].nil?
33
53
  end
@@ -0,0 +1,11 @@
1
+ public struct <%= model.name %> {
2
+ <% model.properties.each do |property| %><%= """public var #{property.key}: #{property.type}""" %>
3
+ <% end %>
4
+ static let tableName = "<%= model.table_name %>"
5
+
6
+ public enum Column: String, Unwrapped {
7
+ <% model.properties.each do |property| %><%= """case #{property.key} = \"#{property.key}\"""" %>
8
+ <% end %>
9
+ var unwrapped: String { get { return self.rawValue.unwrapped } }
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ //
2
+ // <%= model.name %>.swift
3
+ // MetaModel
4
+ //
5
+ // Created by MetaModel.
6
+ // Copyright © 2016 MetaModel. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+ import SQLite
@@ -0,0 +1,6 @@
1
+ extension <%= model.name %> {
2
+ static func initialize() {
3
+ let initializeTableSQL = "<%= model.build_table %>"
4
+ executeSQL(initializeTableSQL)
5
+ }
6
+ }
@@ -0,0 +1,40 @@
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| %>
10
+ <%= """mutating func update(#{property.key} #{property.key}: #{property.type}) -> #{model.name} {
11
+ return self.update([.#{property.key}: #{property.key}])
12
+ }""" %>
13
+ <% end %>
14
+
15
+ mutating func update(attributes: [<%= model.name %>.Column: Any]) -> <%= model.name %> {
16
+ var setSQL: [String] = []
17
+ for (key, _) in attributes {
18
+ switch key {
19
+ <% model.properties_exclude_id.each do |property| %>
20
+ <%= """case .#{property.key}: setSQL.append(\"\(key.unwrapped) = \(self.(#{property.key}#{property.is_optional? ? "?" : ""}.unwrapped)\")
21
+ """ %>
22
+ <% end %>
23
+ default: break
24
+ }
25
+ }
26
+ let updateSQL = "UPDATE \(<%= model.name %>.tableName.unwrapped) SET \(setSQL.joinWithSeparator(", ")) \(itself)"
27
+ executeSQL(updateSQL) {
28
+ for (key, value) in attributes {
29
+ switch key {
30
+ <% model.properties_exclude_id.each do |property| %>
31
+ <%= """case .#{property.key}: self.#{property.key} = value as#{property.is_optional? ? "?" : "!"} #{property.type_without_optional}
32
+ """ %>
33
+ <% end %>
34
+ default: break
35
+ }
36
+ }
37
+ }
38
+ return self
39
+ }
40
+ }
@@ -0,0 +1,16 @@
1
+ extension <%= model.name %> {
2
+ public init(json: [String: Any]) {
3
+ let id: Int = json["id"] as! Int
4
+ <% model.properties_exclude_id.each do |property| %>
5
+ <%= """let #{property.key}: #{property.type} = json[\"#{property.key}\"] as! #{property.type}
6
+ """ %>
7
+ <% end %>
8
+
9
+ self.init(<%= model.property_key_value_pairs %>)
10
+ }
11
+
12
+ public init(jsonData: NSData) throws {
13
+ let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: .AllowFragments) as! [String: Any]
14
+ self.init(json: json)
15
+ }
16
+ }
@@ -0,0 +1,49 @@
1
+ //
2
+ // MetaModel.swift
3
+ // MetaModel
4
+ //
5
+ // Created by MetaModel.
6
+ // Copyright © 2016 MetaModel. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+ import SQLite
11
+
12
+ let path = NSSearchPathForDirectoriesInDomains(
13
+ .DocumentDirectory, .UserDomainMask, true
14
+ ).first! as String
15
+
16
+ let db = try! Connection("\(path)/metamodel_db.sqlite3")
17
+
18
+ public class MetaModel {
19
+ public static func initialize() {
20
+ <% models.each do |model| %><%= "#{model.name}.initialize()" %>
21
+ <% end %>
22
+ }
23
+ }
24
+
25
+ func executeSQL(sql: String, success: (() -> ())? = nil) -> Statement? {
26
+ defer { print("\n") }
27
+ print("-> Begin Transaction")
28
+ let startDate = NSDate()
29
+ do {
30
+ let result = try db.run(sql)
31
+ let endDate = NSDate()
32
+ let interval = endDate.timeIntervalSinceDate(startDate) * 1000
33
+ print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
34
+ print("-> Commit Transaction")
35
+
36
+ if let success = success {
37
+ success()
38
+ }
39
+
40
+ return result
41
+ } catch let error {
42
+ let endDate = NSDate()
43
+ let interval = endDate.timeIntervalSinceDate(startDate) * 1000
44
+ print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
45
+ print("\t\(error)")
46
+ print("-> Rollback transaction")
47
+ }
48
+ return nil
49
+ }
@@ -0,0 +1,61 @@
1
+ public extension <%= model.name %> {
2
+ static var all: <%= model.relation_name %> {
3
+ get { return <%= model.relation_name %>() }
4
+ }
5
+
6
+ static func first(length: UInt) -> <%= model.relation_name %> {
7
+ return <%= model.relation_name %>().orderBy(.id, asc: true).limit(length)
8
+ }
9
+
10
+ static func last(length: UInt) -> <%= model.relation_name %> {
11
+ return <%= model.relation_name %>().orderBy(.id, asc: false).limit(length)
12
+ }
13
+
14
+ static func find(id: Int) -> <%= model.name %>? {
15
+ return <%= model.relation_name %>().find(id).first
16
+ }
17
+
18
+ static func findBy(id id: Int) -> <%= model.name %>? {
19
+ return <%= model.relation_name %>().findBy(id: id).first
20
+ }
21
+
22
+ <% model.properties_exclude_id.each do |property| %><%= """static func findBy(#{property.key} #{property.key}: #{property.type_without_optional}) -\> #{model.name}? {
23
+ return #{model.relation_name}().findBy(#{property.key}: #{property.key}).first
24
+ }""" %>
25
+ <% end %>
26
+ static func filter(column: <%= model.name %>.Column, value: Any) -> <%= model.relation_name %> {
27
+ return <%= model.relation_name %>().filter([column: value])
28
+ }
29
+
30
+ static func filter(conditions: [<%= model.name %>.Column: Any]) -> <%= model.relation_name %> {
31
+ return <%= model.relation_name %>().filter(conditions)
32
+ }
33
+
34
+ static func limit(length: UInt, offset: UInt = 0) -> <%= model.relation_name %> {
35
+ return <%= model.relation_name %>().limit(length, offset: offset)
36
+ }
37
+
38
+ static func take(length: UInt) -> <%= model.relation_name %> {
39
+ return limit(length)
40
+ }
41
+
42
+ static func offset(offset: UInt) -> <%= model.relation_name %> {
43
+ return <%= model.relation_name %>().offset(offset)
44
+ }
45
+
46
+ static func groupBy(columns: <%= model.name %>.Column...) -> <%= model.relation_name %> {
47
+ return <%= model.relation_name %>().groupBy(columns)
48
+ }
49
+
50
+ static func groupBy(columns: [<%= model.name %>.Column]) -> <%= model.relation_name %> {
51
+ return <%= model.relation_name %>().groupBy(columns)
52
+ }
53
+
54
+ static func orderBy(column: <%= model.name %>.Column) -> <%= model.relation_name %> {
55
+ return <%= model.relation_name %>().orderBy(column)
56
+ }
57
+
58
+ static func orderBy(column: <%= model.name %>.Column, asc: Bool) -> <%= model.relation_name %> {
59
+ return <%= model.relation_name %>().orderBy(column, asc: asc)
60
+ }
61
+ }
@@ -0,0 +1,82 @@
1
+ public class <%= model.relation_name %>: Relation<<%= model.name %>> {
2
+ override init() {
3
+ super.init()
4
+ self.select = "SELECT \(<%= model.name %>.tableName.unwrapped).* FROM \(<%= model.name %>.tableName.unwrapped)"
5
+ }
6
+
7
+ func expandColumn(column: <%= model.name %>.Column) -> String {
8
+ return "\(<%= model.name %>.tableName.unwrapped).\(column.unwrapped)"
9
+ }
10
+
11
+ // MARK: Query
12
+
13
+ public func find(id: Int) -> Self {
14
+ return self.findBy(id: id)
15
+ }
16
+
17
+ public func findBy(id id: Int) -> Self {
18
+ return self.filter([.id: id]).limit(1)
19
+ }
20
+
21
+ <% model.properties_exclude_id.each do |property| %>
22
+ <%= """public func findBy(#{property.key} #{property.key}: #{property.type_without_optional}) -\> Self {
23
+ return self.filter([.#{property.key}: #{property.key}]).limit(1)
24
+ }""" %>
25
+ <% end %>
26
+
27
+ public func filter(conditions: [<%= model.name %>.Column: Any]) -> Self {
28
+ for (column, value) in conditions {
29
+ let columnSQL = "\(expandColumn(column))"
30
+
31
+ func filterByEqual(value: Any) {
32
+ self.filter.append("\(columnSQL) = \(value)")
33
+ }
34
+
35
+ func filterByIn(value: [String]) {
36
+ self.filter.append("\(columnSQL) IN (\(value.joinWithSeparator(", ")))")
37
+ }
38
+
39
+ if let value = value as? String {
40
+ filterByEqual(value.unwrapped)
41
+ } else if let value = value as? Int {
42
+ filterByEqual(value)
43
+ } else if let value = value as? Double {
44
+ filterByEqual(value)
45
+ } else if let value = value as? [String] {
46
+ filterByIn(value.map { $0.unwrapped })
47
+ } else if let value = value as? [Int] {
48
+ filterByIn(value.map { $0.description })
49
+ } else if let value = value as? [Double] {
50
+ filterByIn(value.map { $0.description })
51
+ } else {
52
+ let valueMirror = Mirror(reflecting: value)
53
+ print("!!!: UNSUPPORTED TYPE \(valueMirror.subjectType)")
54
+ }
55
+
56
+ }
57
+ return self
58
+ }
59
+
60
+ public func groupBy(columns: <%= model.name %>.Column...) -> Self {
61
+ return self.groupBy(columns)
62
+ }
63
+
64
+ public func groupBy(columns: [<%= model.name %>.Column]) -> Self {
65
+ func groupBy(column: <%= model.name %>.Column) {
66
+ self.group.append("\(expandColumn(column))")
67
+ }
68
+ _ = columns.flatMap(groupBy)
69
+ return self
70
+ }
71
+
72
+ public func orderBy(column: <%= model.name %>.Column) -> Self {
73
+ self.order.append("\(expandColumn(column))")
74
+ return self
75
+ }
76
+
77
+ public func orderBy(column: <%= model.name %>.Column, asc: Bool) -> Self {
78
+ self.order.append("\(expandColumn(column)) \(asc ? "ASC".unwrapped : "DESC".unwrapped)")
79
+ return self
80
+ }
81
+
82
+ }
@@ -0,0 +1,10 @@
1
+ extension <%= model.name %>: Recordable {
2
+ public init(values: Array<Optional<Binding>>) {
3
+ let id: Int64 = values[0] as! Int64
4
+ <% model.properties_exclude_id.each_with_index do |property, index| %>
5
+ <%= """let #{property.key}: #{property.type} = values[#{index + 1}] as! #{property.type}
6
+ """ %>
7
+ <% end %>
8
+ self.init(id: Int(id)<%= model.property_exclude_id_key_value_pairs %>)
9
+ }
10
+ }
@@ -0,0 +1,39 @@
1
+ public extension <%= model.name %> {
2
+ static func deleteAll() {
3
+ let deleteAllSQL = "DELETE FROM \(tableName.unwrapped)"
4
+ executeSQL(deleteAllSQL)
5
+ }
6
+ static func count() -> Int {
7
+ let countSQL = "SELECT count(*) FROM \(tableName.unwrapped)"
8
+ guard let count = executeSQL(countSQL)?.next()?.first as? Int64 else { return 0 }
9
+ return Int(count)
10
+ }
11
+
12
+ static func new(<%= model.property_exclude_id_key_type_pairs(false) %>) -> <%= model.name %> {
13
+ return <%= model.name %>(id: -1<%= model.property_exclude_id_key_value_pairs %>)
14
+ }
15
+
16
+ static func create(<%= model.property_key_type_pairs %>) -> <%= model.name %>? {
17
+ var columnsSQL: [<%= model.name %>.Column] = []
18
+ var valuesSQL: [Unwrapped] = []
19
+
20
+ columnsSQL.append(.id)
21
+ valuesSQL.append(id)
22
+
23
+ <% model.properties_exclude_id.each do |property| %><% if property.is_optional? %>
24
+ <%= """if let #{property.key} = #{property.key} {
25
+ columnsSQL.append(.#{property.key})
26
+ valuesSQL.append(#{property.key})
27
+ }
28
+ """ %>
29
+ <% else %>
30
+ <%= """columnsSQL.append(.#{property.key})
31
+ valuesSQL.append(#{property.key})
32
+ """ %>
33
+ <% end %><% end %>
34
+
35
+ let insertSQL = "INSERT INTO \(tableName.unwrapped) (\(columnsSQL.map { $0.rawValue }.joinWithSeparator(", "))) VALUES (\(valuesSQL.map { $0.unwrapped }.joinWithSeparator(", ")))"
36
+ guard let _ = executeSQL(insertSQL) else { return nil }
37
+ return <%= model.name %>(<%= model.property_key_value_pairs %>)
38
+ }
39
+ }
@@ -1,5 +1,6 @@
1
1
  module MetaModel
2
-
2
+ # The code in this file is mainly borrowed from cocoapods/user_interface.rb
3
+ # which used to generate output messages to user.
3
4
  module UserInterface
4
5
  require 'colored'
5
6
 
@@ -393,7 +394,7 @@ module MetaModel
393
394
  #
394
395
  # @return [String] The formatted string.
395
396
  #
396
- # @note If CocoaPods is not being run in a terminal or the width of the
397
+ # @note If MetaModel is not being run in a terminal or the width of the
397
398
  # terminal is too small a width of 80 is assumed.
398
399
  #
399
400
  def wrap_string(string, indent = 0)
@@ -1,5 +1,5 @@
1
1
  module MetaModel
2
2
  # The version of the MetaModel command line tool.
3
3
  #
4
- VERSION = '0.0.1'.freeze unless defined? MetaModel::MetaModel
4
+ VERSION = '0.0.2'.freeze unless defined? MetaModel::MetaModel
5
5
  end
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.0.1
4
+ version: 0.0.2
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-08-29 00:00:00.000000000 Z
11
+ date: 2016-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: claide
@@ -151,7 +151,17 @@ files:
151
151
  - lib/metamodel/model/cocoa_model.rb
152
152
  - lib/metamodel/model/cocoa_property.rb
153
153
  - lib/metamodel/model/property_constructor.rb
154
+ - lib/metamodel/template/attributes.swift.erb
155
+ - lib/metamodel/template/file_header.swift.erb
156
+ - lib/metamodel/template/initialize.swift.erb
157
+ - lib/metamodel/template/instance_methods.swift.erb
158
+ - lib/metamodel/template/json.swift.erb
159
+ - lib/metamodel/template/metamodel.swift.erb
154
160
  - lib/metamodel/template/model.swift.erb
161
+ - lib/metamodel/template/model_query.swift.erb
162
+ - lib/metamodel/template/model_relation.swift.erb
163
+ - lib/metamodel/template/recordable.swift.erb
164
+ - lib/metamodel/template/static_methods.swift.erb
155
165
  - lib/metamodel/user_interface.rb
156
166
  - lib/metamodel/version.rb
157
167
  homepage: https://github.com/Draveness/MetaModel