metamodel 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,16 +7,12 @@ module MetaModel
7
7
  attr_reader :dependent
8
8
  attr_accessor :major_model
9
9
  attr_accessor :secondary_model
10
- attr_accessor :through
11
10
 
12
11
  def initialize(name, major_model, secondary_model, relation, args)
13
- # through = args[:through]
14
- through = nil
15
12
  dependent = args[:dependent] || :nullify
16
13
 
17
14
  @name = name.to_s.camelize :lower
18
15
  @relation = relation
19
- @through = through.to_s.camelize.singularize unless through.nil?
20
16
  @dependent = dependent
21
17
  @major_model = major_model
22
18
  @secondary_model = secondary_model
@@ -24,44 +20,52 @@ module MetaModel
24
20
  validate_association
25
21
  end
26
22
 
23
+ def class_name
24
+ "#{major_model.name}#{secondary_model.name}Association".camelize
25
+ end
26
+
27
+ def reverse_class_name
28
+ "#{secondary_model.name}#{major_model.name}Association".camelize
29
+ end
30
+
31
+ def major_model_id
32
+ major_model.foreign_id
33
+ end
34
+
35
+ def secondary_model_id
36
+ secondary_model.foreign_id
37
+ end
38
+
39
+ def hash_value
40
+ self.hash.to_s(16)
41
+ end
42
+
27
43
  def expect_constraint?(constraint)
28
44
  result = true
29
45
  result &= self.major_model == constraint.secondary_model
30
46
  result &= self.secondary_model == constraint.major_model
31
- result &= self.through == constraint.through
32
47
 
33
48
  result &= case [self.relation, constraint.relation]
34
49
  when [:has_one, :belongs_to], [:belongs_to, :has_one] then true
35
50
  when [:belongs_to, :has_many] then
36
51
  return false if self.dependent == :destroy
37
- return true unless constraint.through
38
- return false
52
+ return true
39
53
  when [:has_many, :belongs_to] then
40
54
  return false if constraint.dependent == :destroy
41
- return true unless self.through
42
- return false
55
+ return true
43
56
  when [:has_many, :has_many] then
44
- self.through == constraint.through
57
+ return true
45
58
  else false
46
59
  end
47
60
  result
48
61
  end
49
62
 
50
- def secondary_model_instance
51
- case relation
52
- when :has_many, :has_one then "#{secondary_model.name}.find(privateId)"
53
- when :belongs_to then "#{secondary_model.name}.find(#{secondary_model.foreign_id})"
54
- else ""
55
- end
56
- end
57
-
58
63
  #-------------------------------------------------------------------------#
59
64
 
60
65
  # @!group Validation
61
66
 
62
67
  def validate_association
63
68
  validate_dependent(@dependent)
64
- validate_through(@through)
65
69
  end
66
70
 
67
71
  def validate_dependent(dependent)
@@ -71,12 +75,6 @@ module MetaModel
71
75
  unless supported_dependent_options.include? dependent
72
76
  end
73
77
 
74
- def validate_through(through)
75
- raise Informative, "belongs_to can't coexist with through." \
76
- if !!through && @relation == :belongs_to
77
- end
78
-
79
-
80
78
  #-------------------------------------------------------------------------#
81
79
 
82
80
  # @!group Relation
@@ -100,11 +98,7 @@ module MetaModel
100
98
  end
101
99
 
102
100
  def debug_description
103
- if through
104
- "#{major_model.name}.#{relation}.#{secondary_model.name}.through.#{through.name}.#{dependent}"
105
- else
106
- "#{major_model.name}.#{relation}.#{secondary_model.name}.#{dependent}"
107
- end
101
+ "#{major_model.name}.#{relation}.#{secondary_model.name}.#{dependent}"
108
102
  end
109
103
  end
110
104
  end
@@ -15,10 +15,6 @@ module MetaModel
15
15
  @properties.select { |prop| prop.name == property }.size > 0
16
16
  end
17
17
 
18
- def all_foreign_properties
19
- @properties.select { |element| element.is_foreign? }
20
- end
21
-
22
18
  def properties_exclude_id
23
19
  properties_exclude_property "id"
24
20
  end
@@ -70,19 +66,19 @@ module MetaModel
70
66
  def build_table
71
67
  table = "CREATE TABLE #{table_name}"
72
68
  main_sql = @properties.map do |property|
73
- result = "#{property.name} #{property.database_type}"
69
+ result = "#{property.name.underscore} #{property.database_type}"
74
70
  result << " PRIMARY KEY" if property.is_primary?
75
71
  result << " UNIQUE" if property.is_unique?
76
72
  result << " DEFAULT #{property.default_value}" if property.has_default_value?
77
73
  result
78
74
  end
79
- foreign_sql = @properties.map do |property|
80
- next unless property.is_foreign?
81
- reference_table_name = property.type.tableize
82
- "FOREIGN KEY(#{property.name}) REFERENCES #{reference_table_name}(privateId)"
83
- end
75
+ # foreign_sql = @properties.map do |property|
76
+ # next unless property.is_foreign?
77
+ # reference_table_name = property.type.tableize
78
+ # "FOREIGN KEY(#{property.name}) REFERENCES #{reference_table_name}(privateId)"
79
+ # end
84
80
 
85
- table + "(privateId INTEGER PRIMARY KEY, #{(main_sql + foreign_sql).compact.join(", ")});"
81
+ table + "(private_id INTEGER PRIMARY KEY, #{(main_sql).compact.join(", ")});"
86
82
  end
87
83
 
88
84
  private
@@ -73,10 +73,6 @@ module MetaModel
73
73
  @modifiers.include? :primary
74
74
  end
75
75
 
76
- def is_foreign?
77
- @modifiers[:foreign]
78
- end
79
-
80
76
  def is_optional?
81
77
  @type.to_s.end_with? "?"
82
78
  end
@@ -0,0 +1,29 @@
1
+ //
2
+ // <%= association.class_name %>.swift
3
+ // MetaModel
4
+ //
5
+ // Created by MetaModel.
6
+ // Copyright © 2016 metamodel. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ extension <%= association.class_name %> {
12
+ static func create(<%= association.major_model_id %> <%= association.major_model_id %>: Int, <%= association.secondary_model_id %>: Int) {
13
+ executeSQL("INSERT INTO \(<%= association.class_name %>.tableName) (<%= association.major_model_id.underscore %>, <%= association.secondary_model_id.underscore %>) VALUES (\(<%= association.major_model_id %>), \(<%= association.secondary_model_id %>))")
14
+ }
15
+ }
16
+
17
+ public extension <%= association.major_model.name %> {
18
+ var <%= association.name %>: <%= association.secondary_model.name %>? {
19
+ get {
20
+ guard let id = <%= association.class_name %>.findBy(<%= association.major_model.foreign_id %>: privateId).first?.commentId else { return nil }
21
+ return <%= association.secondary_model.name %>.find(id)
22
+ }
23
+ set {
24
+ guard let newValue = newValue else { return }
25
+ <%= association.class_name %>.findBy(<%= association.major_model_id %>: privateId).forEach { $0.delete() }
26
+ <%= association.class_name %>.create(<%= association.major_model_id %>: newValue.privateId, <%= association.secondary_model_id %>: privateId)
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,99 @@
1
+ //
2
+ // <%= association.class_name %>.swift
3
+ // MetaModel
4
+ //
5
+ // Created by MetaModel.
6
+ // Copyright © 2016 metamodel. All rights reserved.
7
+ //
8
+
9
+ import Foundation
10
+
11
+ typealias <%= association.reverse_class_name %> = <%= association.class_name %>
12
+
13
+ struct <%= association.class_name %> {
14
+ var privateId: Int = 0
15
+ var <%= association.major_model_id %>: Int = 0
16
+ var <%= association.secondary_model_id %>: Int = 0
17
+
18
+ enum Association: String, CustomStringConvertible {
19
+ case privateId = "private_id"
20
+ case <%= association.major_model_id %> = "<%= association.major_model_id.underscore %>"
21
+ case <%= association.secondary_model_id %> = "<%= association.secondary_model_id.underscore %>"
22
+ var description: String { get { return self.rawValue } }
23
+ }
24
+ <% [association.major_model, association.secondary_model].each do |model| %>
25
+ <%= """static func findBy(#{model.foreign_id} #{model.foreign_id}: Int) -> [#{association.class_name}] {
26
+ let query = \"SELECT * FROM \\(tableName) WHERE \\(Association.#{model.foreign_id}) = \\(#{model.foreign_id})\"
27
+
28
+ var models: [#{association.class_name}] = []
29
+ guard let stmt = executeSQL(query) else { return models }
30
+ for values in stmt {
31
+ let association = #{association.class_name}(values: values)
32
+ models.append(association)
33
+ }
34
+ return models
35
+ }""" %>
36
+ <% end %>
37
+ func delete() {
38
+ executeSQL("DELETE * FROM \(<%= association.class_name %>.tableName) WHERE \(Association.privateId) = \(privateId)")
39
+ }
40
+ }
41
+
42
+ extension <%= association.class_name %> {
43
+ static func create(<%= association.major_model_id %> <%= association.major_model_id %>: Int, <%= association.secondary_model_id %>: Int) {
44
+ executeSQL("INSERT INTO \(<%= association.class_name %>.tableName) (<%= association.major_model_id.underscore %>, <%= association.secondary_model_id.underscore %>) VALUES (\(<%= association.major_model_id %>), \(<%= association.secondary_model_id %>))")
45
+ }
46
+ }
47
+
48
+ extension <%= association.class_name %> {
49
+ init(values: Array<Optional<Binding>>) {
50
+ let privateId: Int64 = values[0] as! Int64
51
+ let <%= association.major_model_id %>: Int64 = values[1] as! Int64
52
+ let <%= association.secondary_model_id %>: Int64 = values[2] as! Int64
53
+
54
+ self.init(privateId: Int(privateId), <%= association.major_model_id %>: Int(<%= association.major_model_id %>), <%= association.secondary_model_id %>: Int(<%= association.secondary_model_id %>))
55
+ }
56
+ }
57
+
58
+ extension <%= association.class_name %> {
59
+
60
+ static let tableName = "<%= association.class_name.underscore %>"
61
+ static func initialize() {
62
+ let initializeTableSQL = "CREATE TABLE \(tableName)(" +
63
+ "private_id INTEGER PRIMARY KEY, " +
64
+ "<%= association.major_model_id.underscore %> INTEGER NOT NULL, " +
65
+ "<%= association.secondary_model_id.underscore %> INTEGER NOT NULL, " +
66
+ "FOREIGN KEY(<%= association.major_model_id.underscore %>) REFERENCES <%= association.major_model.table_name %>(private_id)," +
67
+ "FOREIGN KEY(<%= association.secondary_model_id.underscore %>) REFERENCES <%= association.secondary_model.table_name %>(private_id)" +
68
+ ");"
69
+
70
+ executeSQL(initializeTableSQL)
71
+ }
72
+ static func deinitialize() {
73
+ let dropTableSQL = "DROP TABLE \(tableName)"
74
+ executeSQL(dropTableSQL)
75
+ }
76
+ }
77
+
78
+ public extension <%= association.major_model.name %> {
79
+ var <%= association.name %>: [<%= association.secondary_model.name %>] {
80
+ get {
81
+ let ids = <%= association.class_name %>.findBy(<%= association.major_model_id %>: privateId).map { $0.<%= association.secondary_model_id %> }
82
+ return <%= association.secondary_model.name %>.find(ids).result
83
+ }
84
+ set {
85
+ <%= association.class_name %>.findBy(<%= association.major_model_id %>: privateId).forEach { $0.delete() }
86
+ newValue.forEach { <%= association.class_name %>.create(<%= association.major_model_id %>: privateId, <%= association.secondary_model_id %>: $0.privateId) }
87
+ }
88
+ }
89
+
90
+ func create<%= association.secondary_model.name %>(<%= association.secondary_model.property_key_type_pairs %>) -> <%= association.secondary_model.name %>? {
91
+ guard let result = <%= association.secondary_model.name %>.create(<%= association.secondary_model.property_key_value_pairs %>) else { return nil }
92
+ <%= association.class_name %>.create(<%= association.major_model_id %>: privateId, <%= association.secondary_model_id %>: result.privateId)
93
+ return result
94
+ }
95
+
96
+ func append<%= association.secondary_model.name %>(<%= association.secondary_model.property_key_type_pairs %>) -> <%= association.secondary_model.name %>? {
97
+ return create<%= association.secondary_model.name %>(<%= association.secondary_model.property_key_value_pairs %>)
98
+ }
99
+ }
@@ -1,11 +1,9 @@
1
1
  // MAKR: - Helper
2
2
 
3
3
  public class <%= model.relation_name %>: Relation<<%= model.name %>> {
4
- <% model.all_foreign_properties.each do |foreign_property| %><%= """var #{foreign_property.name} = 0
5
- """%><% end %>
6
4
  override init() {
7
5
  super.init()
8
- self.select = "SELECT \(<%= model.name %>.tableName.unwrapped).* FROM \(<%= model.name %>.tableName.unwrapped)"
6
+ self.select = "SELECT \(<%= model.name %>.tableName).* FROM \(<%= model.name %>.tableName)"
9
7
  }
10
8
 
11
9
  override var result: [<%= model.name %>] {
@@ -20,7 +18,7 @@ public class <%= model.relation_name %>: Relation<<%= model.name %>> {
20
18
  }
21
19
 
22
20
  func expandColumn(column: <%= model.name %>.Column) -> String {
23
- return "\(<%= model.name %>.tableName.unwrapped).\(column.unwrapped)"
21
+ return "\(<%= model.name %>.tableName).\(column)"
24
22
  }
25
23
  }
26
24
 
@@ -36,7 +34,7 @@ extension <%= model.name %> {
36
34
  }
37
35
 
38
36
  extension <%= model.name %> {
39
- var itself: String { get { return "WHERE \(<%= model.name %>.tableName.unwrapped).\("privateId".unwrapped) = \(privateId)" } }
37
+ var itself: String { get { return "WHERE \(<%= model.name %>.tableName).private_id = \(privateId)" } }
40
38
  }
41
39
 
42
40
  extension <%= model.relation_name %> {
@@ -44,8 +42,12 @@ extension <%= model.relation_name %> {
44
42
  return filter(privateId)
45
43
  }
46
44
 
45
+ func find(privateIds: [Int]) -> Self {
46
+ return filter([.privateId: privateIds])
47
+ }
48
+
47
49
  func filter(privateId: Int) -> Self {
48
- self.filter.append("\"privateId\" = \(privateId)")
50
+ self.filter.append("private_id = \(privateId)")
49
51
  return self
50
52
  }
51
53
  }
@@ -27,5 +27,12 @@ public class MetaModel {
27
27
  #{model.name}.initialize()
28
28
  }""" %>
29
29
  <% end %>
30
+
31
+ <% associations.each do |association| %><% if association.relation.to_s.start_with? "has" %><%= """if infos[#{association.class_name}.tableName] != \"#{association.hash_value}\" {
32
+ updateMetaModelTableInfos(#{association.class_name}.tableName, hashValue: \"#{association.hash_value}\")
33
+ #{association.class_name}.deinitialize()
34
+ #{association.class_name}.initialize()
35
+ }""" %>
36
+ <% end %><% end %>
30
37
  }
31
38
  }
@@ -3,11 +3,8 @@
3
3
  public extension <%= model.name %> {
4
4
  var delete: Bool {
5
5
  get {
6
- let deleteSQL = "DELETE FROM \(<%= model.name %>.tableName.unwrapped) \(itself)"
7
- executeSQL(deleteSQL)<% model.associations.each do |association| %>
8
- <%= association.secondary_model_instance + "?.delete" if association.dependent == :destroy %>
9
- <%= association.secondary_model_instance + "?.update(#{model.foreign_id}: 0)" if association.dependent == :nullify && model.contains?(model.foreign_id) %>
10
- <% end %>
6
+ let deleteSQL = "DELETE FROM \(<%= model.name %>.tableName) \(itself)"
7
+ executeSQL(deleteSQL)
11
8
  return true
12
9
  }
13
10
  }
@@ -4,11 +4,12 @@ public struct <%= model.name %> {
4
4
  <% end %>
5
5
  static let tableName = "<%= model.table_name %>"
6
6
 
7
- public enum Column: String, Unwrapped {
8
- <% model.properties.each do |property| %><%= """case #{property.name} = \"#{property.name}\"""" %>
7
+ public enum Column: String, CustomStringConvertible {
8
+ <% model.properties.each do |property| %><%= """case #{property.name} = \"#{property.name.underscore}\"""" %>
9
9
  <% end %>
10
- case privateId = "privateId"
11
- var unwrapped: String { get { return self.rawValue.unwrapped } }
10
+ case privateId = "private_id"
11
+
12
+ public var description: String { get { return self.rawValue } }
12
13
  }
13
14
 
14
15
  public init(<%= model.property_key_type_pairs false %>) {
@@ -34,7 +35,7 @@ public struct <%= model.name %> {
34
35
  <%= """columnsSQL.append(.#{property.name})
35
36
  valuesSQL.append(#{property.name})
36
37
  """ %><% end %><% end %>
37
- let insertSQL = "INSERT INTO \(tableName.unwrapped) (\(columnsSQL.map { $0.rawValue }.joinWithSeparator(", "))) VALUES (\(valuesSQL.map { $0.unwrapped }.joinWithSeparator(", ")))"
38
+ let insertSQL = "INSERT INTO \(tableName) (\(columnsSQL.map { $0.rawValue }.joinWithSeparator(", "))) VALUES (\(valuesSQL.map { $0.unwrapped }.joinWithSeparator(", ")))"
38
39
  guard let _ = executeSQL(insertSQL),
39
40
  let lastInsertRowId = executeScalarSQL("SELECT last_insert_rowid();") as? Int64 else { return nil }
40
41
  var result = <%= model.name %>(<%= model.property_key_value_pairs %>)
@@ -42,16 +43,3 @@ public struct <%= model.name %> {
42
43
  return result
43
44
  }
44
45
  }
45
-
46
- public extension <%= model.relation_name %> {
47
- <% model.all_foreign_properties.each do |property| %>
48
- func create(<%= model.property_key_type_pairs_without_property property.name %>) -> <%= model.name %>? {
49
- return <%= model.name %>.create(<% if model.properties_exclude_property(property).count == 0 %><%= "#{property}: property" %><% else %><%= model.property_key_value_pairs %><% end %>)
50
- }
51
-
52
- func append(element: <%= model.name %>) {
53
- var element = element
54
- element.<%= property.name %> = <%= property.name %>
55
- }
56
- <% end %>
57
- }
@@ -29,6 +29,10 @@ public extension <%= model.name %> {
29
29
  return <%= model.relation_name %>().find(id).first
30
30
  }
31
31
 
32
+ static func find(ids: [Int]) -> <%= model.relation_name %> {
33
+ return <%= model.relation_name %>().find(ids)
34
+ }
35
+
32
36
  static func findBy(<%= model.property_key_type_pairs(true, true) %>) -> <%= model.relation_name %> {
33
37
  return <%= model.relation_name %>().findBy(<%= model.property_key_value_pairs %>)
34
38
  }
@@ -90,13 +94,13 @@ public extension <%= model.relation_name %> {
90
94
  }
91
95
 
92
96
  if let value = value as? String {
93
- filterByEqual(value.unwrapped)
97
+ filterByEqual(value)
94
98
  } else if let value = value as? Int {
95
99
  filterByEqual(value)
96
100
  } else if let value = value as? Double {
97
101
  filterByEqual(value)
98
102
  } else if let value = value as? [String] {
99
- filterByIn(value.map { $0.unwrapped })
103
+ filterByIn(value.map { $0 })
100
104
  } else if let value = value as? [Int] {
101
105
  filterByIn(value.map { $0.description })
102
106
  } else if let value = value as? [Double] {
@@ -128,7 +132,7 @@ public extension <%= model.relation_name %> {
128
132
  }
129
133
 
130
134
  func orderBy(column: <%= model.name %>.Column, asc: Bool) -> Self {
131
- self.order.append("\(expandColumn(column)) \(asc ? "ASC".unwrapped : "DESC".unwrapped)")
135
+ self.order.append("\(expandColumn(column)) \(asc ? "ASC" : "DESC")")
132
136
  return self
133
137
  }
134
138
  }
@@ -13,11 +13,11 @@ public extension <%= model.name %> {
13
13
  if let attributes = attributes as? [<%= model.name %>.Column: Unwrapped] {
14
14
  for (key, value) in attributes {
15
15
  switch key {
16
- <% model.properties_exclude_id.each do |property| %><%= """case .#{property.name}: setSQL.append(\"\\(key.unwrapped) = \\(value.unwrapped)\")""" %>
16
+ <% model.properties_exclude_id.each do |property| %><%= """case .#{property.name}: setSQL.append(\"\\(key) = \\(value.unwrapped)\")""" %>
17
17
  <% end %>default: break
18
18
  }
19
19
  }
20
- let updateSQL = "UPDATE \(<%= model.name %>.tableName.unwrapped) SET \(setSQL.joinWithSeparator(", ")) \(itself)"
20
+ let updateSQL = "UPDATE \(<%= model.name %>.tableName) SET \(setSQL.joinWithSeparator(", ")) \(itself)"
21
21
  executeSQL(updateSQL) {
22
22
  for (key, value) in attributes {
23
23
  switch key {