metamodel 0.0.1 → 0.0.2

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 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