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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 299648ce9da2c26b4d34f74f90acdfff7dff076c
4
- data.tar.gz: b3d307c710260f446bd61c1b2aa0f049523d92b8
3
+ metadata.gz: 3d443b7aba6c0b4f80775f5d7e785d571cbcaee3
4
+ data.tar.gz: 0a124cd657c3c8e1584d5a106666077cebeafab8
5
5
  SHA512:
6
- metadata.gz: 3ab3d001805ebb322de152d52f9c01a973b3d329ae5fbe532f95d34ddfe3dec7c1c77f9e5c1b048aa2f0ace724c93e1da5de1779ad086d0adb4c167a3f2d8733
7
- data.tar.gz: 3faf5fff2d4738bfe1fe140ce83f4c9f52ac8ab5548836f2863ae2d229496d5cc4621b467bf524af8d7f7c3ed28e68b55c7e8aa03e10e1bf3393206de3f9b1ad
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 to model constructor and a bunch of APIs which provides an approach of handling client side database very easily.
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 |j|
40
+ define :User do
41
41
  # define User model like this
42
- j.nickname :string
43
- j.avatar :string
44
- j.email :string, :unique, default: "default@gmail.com"
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 Linked Frameworks and Libraries phrase.
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 **Linked frameworks and Libraries** phrase which located in `General` tab.
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/cocoa_model'
9
- require 'metamodel/model/cocoa_property'
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
- model = CocoaModel.new(model_name)
39
- yield PropertyConstructor.new(model)
40
- @models << model
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.erb"))
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 Linked Frameworks and Libraries phrase.\n"
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.erb"))
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 |j|
35
+ define :#{model} do
36
36
  # define #{model} model like this
37
- # j.nickname :string
37
+ # attr nickname, :string
38
38
  end
39
39
  TEMPLATE
40
40
  modelfile
@@ -66,7 +66,7 @@ module MetaModel
66
66
  # @return [String]
67
67
  #
68
68
  def metamodel_template_uri
69
- "git@github.com:MetaModel-Framework/MetaModel-Template.git"
69
+ "git@github.com:MModel/MetaModel-Template.git"
70
70
  end
71
71
 
72
72
  # Returns the path of the MetaModel.xcodeproj.
@@ -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 CocoaProperty
3
+ class Property
4
4
  attr_reader :json_key
5
- attr_reader :key
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
- @key = json_key.to_s.camelize(:lower).to_sym
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
- @modifiers[:default].nil?
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.key}: #{property.type}""" %>
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.key} = \"#{property.key}\"""" %>
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.key}: #{property.type} = json[\"#{property.key}\"] as! #{property.type}""" %>
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
- var results: [<%= model.name %>] = []
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, silent: Bool = false, success: (() -> ())? = nil) -> Statement? {
35
- defer { print("\n") }
36
- print("-> Begin Transaction")
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
- print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
54
- print("\t\(error)")
55
- print("-> Rollback transaction")
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, silent: Bool = false, success: (() -> ())? = nil) -> Binding? {
61
- defer { print("\n") }
62
- print("-> Begin Transaction")
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
- print("\tSQL (\(interval.format("0.2"))ms) \(sql)")
68
- print("-> Commit Transaction")
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.key} #{property.key}: #{property.type_without_optional}) -\> #{model.name}? {
23
- return #{model.relation_name}().findBy(#{property.key}: #{property.key}).first
24
- }""" %>
25
- <% end %>
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.key} #{property.key}: #{property.type_without_optional}) -\> Self {
23
- return self.filter([.#{property.key}: #{property.key}]).limit(1)
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.key}: #{property.real_type} = values[#{index}] as! #{property.real_type}""" %>
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.property_exclude_id_key_type_pairs(false) %>) -> <%= model.name %> {
13
- return <%= model.name %>(id: -1<%= model.property_exclude_id_key_value_pairs %>)
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.key} = #{property.key} {
24
- columnsSQL.append(.#{property.key})
25
- valuesSQL.append(#{property.key})
25
+ <%= """if let #{property.name} = #{property.name} {
26
+ columnsSQL.append(.#{property.name})
27
+ valuesSQL.append(#{property.name})
26
28
  }""" %><% else %>
27
- <%= """columnsSQL.append(.#{property.key})
28
- valuesSQL.append(#{property.key})
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(", ")))"
@@ -1,5 +1,5 @@
1
1
  module MetaModel
2
2
  # The version of the MetaModel command line tool.
3
3
  #
4
- VERSION = '0.0.5'.freeze unless defined? MetaModel::MetaModel
4
+ VERSION = '0.1.1'.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.5
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-07 00:00:00.000000000 Z
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/cocoa_model.rb
152
- - lib/metamodel/model/cocoa_property.rb
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
160
- - lib/metamodel/template/model_query.swift.erb
161
- - lib/metamodel/template/model_relation.swift.erb
162
- - lib/metamodel/template/recordable.swift.erb
163
- - lib/metamodel/template/static_methods.swift.erb
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.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
- }