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