puffs 0.2.05 → 0.2.06

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: c18567a1d51b75d3ad758258c55923663e43bd96
4
- data.tar.gz: 35baf154d55ce813ad53d2b260c78a36b3925b14
3
+ metadata.gz: ffc8090b37bd60c44f6e9ab1c3b03a13efdd8245
4
+ data.tar.gz: ee5f09a1613a4536a6ce8e22bae477d532b5b94e
5
5
  SHA512:
6
- metadata.gz: 2e2c6e55a65a3aac467c51b21a93cc845489926d3c33186d6e311533bfdff2fc316ba9c2648a131127ff21cccbf76627b4c35dcbe2d977a20895272fa6be94c2
7
- data.tar.gz: 6a7c885f4e2e91700482a70d8ebe6447f55fea35fb4ed36ee498281439dd1f2b42d1d9ff4d36a7b18a4d1ebc2091da80ab43355d637c3fe2d627edc06efc5c9e
6
+ metadata.gz: 29c2b60efd307a57c81242884f8285d17496fdbec2363063132d28b9b0315b5dfcfbcf7d3694c0c68dd4f450c785849ef9b36e606f7e80cde6c1bb18d7a7c27d
7
+ data.tar.gz: 37f8b2b9207f48566161989d72892203640cae3fa92b2f544f1ccd1cb8d0344c802b5f2e7d0dd8b0404ca8e5bc1817f10616ae87520aa68575d8582319c51773
data/lib/relation.rb CHANGED
@@ -1,7 +1,5 @@
1
- require_relative './../lib/db_connection'
2
- require_relative 'sql_object/sql_object'
3
-
4
1
  module Puffs
2
+ # Queries made through Puffs::SQLObject return instance of SQLRelation
5
3
  class SQLRelation
6
4
  def self.build_association(base, included, method_name)
7
5
  base.included_relations << included
@@ -19,13 +17,13 @@ module Puffs
19
17
 
20
18
  match = proc do
21
19
  selection = included.select do |i_sql_obj|
22
- i_sql_obj.send(i_send) == self.send(b_send)
20
+ i_sql_obj.send(i_send) == send(b_send)
23
21
  end
24
22
 
25
23
  associated = has_many ? selection : selection.first
26
24
 
27
- #After we find our values iteratively, we overwrite the method again
28
- #to the result values to reduce future lookup time to O(1).
25
+ # After we find our values iteratively, we overwrite the method again
26
+ # to the result values to reduce future lookup time to O(1).
29
27
  new_match = proc { associated }
30
28
  Puffs::SQLObject.define_singleton_method_by_proc(
31
29
  self, method_name, new_match)
@@ -33,8 +31,9 @@ module Puffs
33
31
  associated
34
32
  end
35
33
 
36
- #we overwrite the association method for each SQLObject in the
37
- #collection so that it points to our cached relation and doesn't fire a query.
34
+ # We overwrite the association method for each SQLObject in the
35
+ # collection so that it points to our cached relation and
36
+ # doesn't fire a query.
38
37
  base.collection.each do |b_sql_obj|
39
38
  Puffs::SQLObject.define_singleton_method_by_proc(
40
39
  b_sql_obj, method_name, match)
@@ -46,21 +45,20 @@ module Puffs
46
45
 
47
46
  def initialize(options)
48
47
  defaults =
49
- {
50
- klass: nil,
51
- loaded: false,
52
- collection: []
53
- }
48
+ {
49
+ loaded: false,
50
+ collection: []
51
+ }
52
+
53
+ merged_options = defaults.merge(options)
54
54
 
55
55
  @klass = options[:klass]
56
- @collection = options[:collection] || defaults[:collection]
57
- @loaded = options[:loaded] || defaults[:loaded]
56
+ @collection = merged_options[:collection]
57
+ @loaded = merged_options[:loaded]
58
58
  end
59
59
 
60
60
  def <<(item)
61
- if item.class == klass
62
- @collection << item
63
- end
61
+ @collection << item if item.class == klass
64
62
  end
65
63
 
66
64
  def count
@@ -87,13 +85,13 @@ module Puffs
87
85
  end
88
86
 
89
87
  def load
90
- if !loaded
88
+ unless loaded
91
89
  puts "LOADING #{table_name}"
92
- results = Puffs::DBConnection.execute(<<-SQL, sql_params[:values])
90
+ results = Puffs::DBConnection.execute(<<-SQL, sql_params[:values])
93
91
  SELECT
94
- #{sql_count ? "COUNT(*)" : self.table_name.to_s + ".*"}
92
+ #{sql_count ? 'COUNT(*)' : table_name.to_s + '.*'}
95
93
  FROM
96
- #{self.table_name}
94
+ #{table_name}
97
95
  #{sql_params[:where]}
98
96
  #{sql_params[:params]}
99
97
  #{order_by_string}
@@ -103,56 +101,49 @@ module Puffs
103
101
  results = sql_count ? results.first.values.first : parse_all(results)
104
102
  end
105
103
 
106
- results = results || self
107
-
108
- unless includes_params.empty?
109
- results = load_includes(results)
110
- end
111
-
104
+ results ||= self
105
+ results = load_includes(results) unless includes_params.empty?
112
106
  results
113
107
  end
114
108
 
115
109
  def load_includes(relation)
116
110
  includes_params.each do |param|
117
- if relation.klass.has_association?(param)
118
- puts "LOADING #{param.to_s}"
119
- assoc = klass.assoc_options[param]
120
- f_k = assoc.foreign_key
121
- p_k = assoc.primary_key
122
- includes_table = assoc.table_name.to_s
123
- in_ids = relation.collection.map do |sqlobject|
124
- sqlobject.id
125
- end.join(", ")
126
-
127
- has_many = assoc.class == HasManyOptions
128
-
129
- results = Puffs::DBConnection.execute(<<-SQL)
130
- SELECT
131
- #{includes_table}.*
132
- FROM
133
- #{includes_table}
134
- WHERE
135
- #{includes_table}.#{has_many ? f_k : p_k}
136
- IN
137
- (#{in_ids});
138
- SQL
139
- included = assoc.model_class.parse_all(results)
140
- SQLRelation.build_association(relation, included, param)
141
- end
111
+ next unless relation.klass.has_association?(param)
112
+
113
+ puts "LOADING #{param}"
114
+ assoc = klass.assoc_options[param]
115
+ f_k = assoc.foreign_key
116
+ p_k = assoc.primary_key
117
+ includes_table = assoc.table_name.to_s
118
+ in_ids = relation.collection.map(&:id).join(', ')
119
+ has_many = assoc.class == HasManyOptions
120
+
121
+ results = Puffs::DBConnection.execute(<<-SQL)
122
+ SELECT
123
+ #{includes_table}.*
124
+ FROM
125
+ #{includes_table}
126
+ WHERE
127
+ #{includes_table}.#{has_many ? f_k : p_k}
128
+ IN
129
+ (#{in_ids});
130
+ SQL
131
+ included = assoc.model_class.parse_all(results)
132
+ SQLRelation.build_association(relation, included, param)
142
133
  end
143
134
 
144
135
  relation
145
136
  end
146
137
 
147
138
  def method_missing(method, *args, &block)
148
- self.to_a.send(method, *args, &block)
139
+ to_a.send(method, *args, &block)
149
140
  end
150
141
 
151
142
  def order(params)
152
143
  if params.is_a?(Hash)
153
144
  order_params_hash.merge!(params)
154
145
  else
155
- order_params_hash.merge!(params => :asc)
146
+ order_params_hash[params] = :asc
156
147
  end
157
148
  self
158
149
  end
@@ -164,17 +155,20 @@ module Puffs
164
155
  def order_by_string
165
156
  hash_string = order_params_hash.map do |column, asc_desc|
166
157
  "#{column} #{asc_desc.to_s.upcase}"
167
- end.join(", ")
158
+ end.join(', ')
168
159
 
169
- hash_string.empty? ? "" : "ORDER BY #{hash_string}"
160
+ hash_string.empty? ? '' : "ORDER BY #{hash_string}"
170
161
  end
171
162
 
172
163
  def parse_all(attributes)
173
- klass.parse_all(attributes).where(where_params_hash).includes(includes_params)
164
+ klass.parse_all(attributes)
165
+ .where(where_params_hash)
166
+ .includes(includes_params)
174
167
  end
175
168
 
176
169
  def sql_params
177
- params, values = [], []
170
+ params = []
171
+ values = []
178
172
 
179
173
  i = 1
180
174
  where_params_hash.map do |attribute, value|
@@ -183,8 +177,8 @@ module Puffs
183
177
  i += 1
184
178
  end
185
179
 
186
- { params: params.join(" AND "),
187
- where: params.empty? ? nil : "WHERE",
180
+ { params: params.join(' AND '),
181
+ where: params.empty? ? nil : 'WHERE',
188
182
  values: values }
189
183
  end
190
184
 
@@ -193,7 +187,7 @@ module Puffs
193
187
  end
194
188
 
195
189
  def to_a
196
- self.load.collection
190
+ load.collection
197
191
  end
198
192
 
199
193
  def where_params_hash
@@ -1,99 +1,119 @@
1
1
  require 'active_support/inflector'
2
2
 
3
- module Puffs
4
- class AssocOptions
5
- attr_accessor(
6
- :foreign_key,
7
- :class_name,
8
- :primary_key
9
- )
10
-
11
- def model_class
12
- class_name.constantize
13
- end
3
+ # Used in HasManyOptions and BelongsToOptions
4
+ class AssocOptions
5
+ attr_accessor(
6
+ :foreign_key,
7
+ :class_name,
8
+ :primary_key
9
+ )
10
+
11
+ def model_class
12
+ class_name.constantize
13
+ end
14
14
 
15
- def table_name
16
- model_class.table_name
17
- end
15
+ def table_name
16
+ model_class.table_name
18
17
  end
18
+ end
19
19
 
20
- class BelongsToOptions < AssocOptions
21
- def initialize(name, options = {})
22
- @primary_key = options[:primary_key] || :id
23
- @foreign_key = options[:foreign_key] || "#{name}_id".to_sym
24
- @class_name = options[:class_name] || name.to_s.capitalize
25
- end
20
+ # Used to build belongs_to associations.
21
+ class BelongsToOptions < AssocOptions
22
+ def initialize(name, options = {})
23
+ defaults = {
24
+ primary_key: :id,
25
+ foreign_key: "#{name}_id".to_sym,
26
+ class_name: name.to_s.capitalize
27
+ }
28
+
29
+ merged_options = defaults.merge(options)
30
+
31
+ @primary_key = merged_options[:primary_key]
32
+ @foreign_key = merged_options[:foreign_key]
33
+ @class_name = merged_options[:class_name]
26
34
  end
35
+ end
27
36
 
28
- class HasManyOptions < AssocOptions
29
- def initialize(name, self_class_name, options = {})
30
- @primary_key = options[:primary_key] || :id
31
- @foreign_key = options[:foreign_key] || "#{self_class_name.to_s.underscore}_id".to_sym
32
- @class_name = options[:class_name] || name.to_s.singularize.camelcase
33
- end
37
+ # Used to build has_many associations.
38
+ class HasManyOptions < AssocOptions
39
+ def initialize(name, self_class_name, options = {})
40
+ defaults = {
41
+ primary_key: :id,
42
+ foreign_key: "#{self_class_name.to_s.underscore}_id".to_sym,
43
+ class_name: name.to_s.singularize.camelcase
44
+ }
45
+
46
+ merged_options = defaults.merge(options)
47
+
48
+ @primary_key = merged_options[:primary_key]
49
+ @foreign_key = merged_options[:foreign_key]
50
+ @class_name = merged_options[:class_name]
34
51
  end
52
+ end
35
53
 
36
- module Associatable
37
- def belongs_to(name, options = {})
38
- options = BelongsToOptions.new(name, options)
39
- assoc_options[name] = options
54
+ # Used to map association methods.
55
+ module Associatable
56
+ def belongs_to(name, options = {})
57
+ options = BelongsToOptions.new(name, options)
58
+ assoc_options[name] = options
40
59
 
41
- define_method(name) do
42
- foreign_key_value = self.send(options.foreign_key)
43
- return nil if foreign_key_value.nil?
60
+ define_method(name) do
61
+ foreign_key_value = send(options.foreign_key)
62
+ return nil if foreign_key_value.nil?
44
63
 
45
- options.model_class
46
- .where(options.primary_key => foreign_key_value)
47
- .first
48
- end
64
+ options.model_class
65
+ .where(options.primary_key => foreign_key_value)
66
+ .first
49
67
  end
68
+ end
50
69
 
51
- def has_many(name, options = {})
52
- options = HasManyOptions.new(name, self.to_s, options)
53
- assoc_options[name] = options
54
-
55
- define_method(name) do
56
- target_key_value = self.send(options.primary_key)
57
- return nil if target_key_value.nil?
58
- options.model_class
59
- .where(options.foreign_key => target_key_value)
60
- .to_a
61
- end
62
- end
70
+ def has_many(name, options = {})
71
+ options = HasManyOptions.new(name, to_s, options)
72
+ assoc_options[name] = options
63
73
 
64
- def assoc_options
65
- @assoc_options ||= {}
74
+ define_method(name) do
75
+ target_key_value = send(options.primary_key)
76
+ return nil if target_key_value.nil?
77
+ options.model_class
78
+ .where(options.foreign_key => target_key_value)
79
+ .to_a
66
80
  end
81
+ end
82
+
83
+ def assoc_options
84
+ @assoc_options ||= {}
85
+ end
67
86
 
68
- def has_one_through(name, through_name, source_name)
69
- through_options = assoc_options[through_name]
87
+ def has_one_through(name, through_name, source_name)
88
+ through_options = assoc_options[through_name]
70
89
 
71
- define_method(name) do
72
- source_options =
73
- through_options.model_class.assoc_options[source_name]
74
- through_pk = through_options.primary_key
75
- key_val = self.send(through_options.foreign_key)
90
+ define_method(name) do
91
+ source_options =
92
+ through_options.model_class.assoc_options[source_name]
93
+ through_pk = through_options.primary_key
94
+ key_val = send(through_options.foreign_key)
76
95
 
77
- source_options.model_class.includes(through_options.model_class)
78
- .where(through_pk => key_val).first
79
- end
96
+ source_options.model_class
97
+ .includes(through_options.model_class)
98
+ .where(through_pk => key_val)
99
+ .first
80
100
  end
101
+ end
81
102
 
82
- def has_many_through(name, through_name, source_name)
83
- through_options = assoc_options[through_name]
84
- define_method(name) do
85
- through_fk = through_options.foreign_key
86
- through_class = through_options.model_class
87
- key_val = self.send(through_options.primary_key)
88
-
89
- #2 queries, we could reduce to 1 by writing Puffs::SQLRelation.join.
90
- through_class.where(through_fk => key_val)
91
- .includes(source_name)
92
- .load
93
- .included_relations
94
- .first
95
- .to_a
96
- end
103
+ def has_many_through(name, through_name, source_name)
104
+ through_options = assoc_options[through_name]
105
+ define_method(name) do
106
+ through_fk = through_options.foreign_key
107
+ through_class = through_options.model_class
108
+ key_val = send(through_options.primary_key)
109
+
110
+ # 2 queries, we could reduce to 1 by writing Puffs::SQLRelation.join.
111
+ through_class.where(through_fk => key_val)
112
+ .includes(source_name)
113
+ .load
114
+ .included_relations
115
+ .first
116
+ .to_a
97
117
  end
98
118
  end
99
119
  end
@@ -0,0 +1,32 @@
1
+ # Search methods for Puffs::SQLObject
2
+ module Searchable
3
+ RELATION_METHODS = [
4
+ :limit, :includes, :where, :order
5
+ ].freeze
6
+
7
+ RELATION_METHODS.each do |method|
8
+ define_method(method) do |arg|
9
+ Puffs::SQLRelation.new(klass: self).send(method, arg)
10
+ end
11
+ end
12
+
13
+ def all
14
+ where({})
15
+ end
16
+
17
+ def count
18
+ all.count
19
+ end
20
+
21
+ def find(id)
22
+ where(id: id).first
23
+ end
24
+
25
+ def first
26
+ all.limit(1).first
27
+ end
28
+
29
+ def last
30
+ all.order(id: :desc).limit(1).first
31
+ end
32
+ end
@@ -1,48 +1,30 @@
1
+ require 'active_support/inflector'
1
2
  require_relative '../../lib/db_connection'
2
3
  require_relative 'associatable'
3
4
  require_relative '../relation'
4
- require 'active_support/inflector'
5
- # require_relative '../puffs'
5
+ require_relative 'searchable'
6
6
 
7
7
  module Puffs
8
+ # Base Model class for Puffs Orm.
8
9
  class SQLObject
9
10
  extend Associatable
10
-
11
- RELATION_METHODS = [
12
- :limit, :includes, :where, :order
13
- ]
14
-
15
- RELATION_METHODS.each do |method|
16
- define_singleton_method(method) do |arg|
17
- Puffs::SQLRelation.new(klass: self).send(method, arg)
18
- end
19
- end
20
-
21
- def self.all
22
- where({})
23
- end
11
+ extend Searchable
24
12
 
25
13
  def self.columns
26
14
  Puffs::DBConnection.columns(table_name)
27
15
  end
28
16
 
29
- def self.count
30
- all.count
31
- end
32
-
33
17
  def self.define_singleton_method_by_proc(obj, name, block)
34
18
  metaclass = class << obj; self; end
35
19
  metaclass.send(:define_method, name, block)
36
20
  end
37
21
 
38
22
  def self.destroy_all!
39
- self.all.each do |entry|
40
- entry.destroy!
41
- end
23
+ all.each(&:destroy!)
42
24
  end
43
25
 
44
26
  def self.finalize!
45
- self.columns.each do |column|
27
+ columns.each do |column|
46
28
  define_method(column) do
47
29
  attributes[column]
48
30
  end
@@ -53,26 +35,14 @@ module Puffs
53
35
  end
54
36
  end
55
37
 
56
- def self.find(id)
57
- where(id: id).first
58
- end
59
-
60
- def self.first
61
- all.limit(1).first
62
- end
63
-
64
38
  def self.has_association?(association)
65
39
  assoc_options.keys.include?(association)
66
40
  end
67
41
 
68
- def self.last
69
- all.order(id: :desc).limit(1).first
70
- end
71
-
72
42
  def self.parse_all(results)
73
43
  relation = Puffs::SQLRelation.new(klass: self, loaded: true)
74
44
  results.each do |result|
75
- relation << self.new(result)
45
+ relation << new(result)
76
46
  end
77
47
 
78
48
  relation
@@ -83,7 +53,7 @@ module Puffs
83
53
  end
84
54
 
85
55
  def self.table_name
86
- @table_name ||= self.to_s.downcase.tableize
56
+ @table_name ||= to_s.downcase.tableize
87
57
  end
88
58
 
89
59
  def initialize(params = {})
@@ -92,7 +62,7 @@ module Puffs
92
62
  raise "unknown attribute '#{attr_name}'"
93
63
  end
94
64
 
95
- self.send("#{attr_name}=", value)
65
+ send("#{attr_name}=", value)
96
66
  end
97
67
  end
98
68
 
@@ -102,7 +72,7 @@ module Puffs
102
72
 
103
73
  def attribute_values
104
74
  self.class.columns.map do |column|
105
- self.send(column)
75
+ send(column)
106
76
  end
107
77
  end
108
78
 
@@ -121,9 +91,9 @@ module Puffs
121
91
 
122
92
  def insert
123
93
  columns = self.class.columns.reject { |col| col == :id }
124
- column_values = columns.map {|attr_name| send(attr_name)}
125
- column_names = columns.join(", ")
126
- bind_params = (1..columns.length).map {|n| "$#{n}"}.join(", ")
94
+ column_values = columns.map { |attr_name| send(attr_name) }
95
+ column_names = columns.join(', ')
96
+ bind_params = (1..columns.length).map { |n| "$#{n}" }.join(', ')
127
97
  result = Puffs::DBConnection.execute(<<-SQL, column_values)
128
98
  INSERT INTO
129
99
  #{self.class.table_name} (#{column_names})
@@ -141,8 +111,8 @@ module Puffs
141
111
 
142
112
  def update
143
113
  set_line = self.class.columns.map do |column|
144
- "#{column} = \'#{self.send(column)}\'"
145
- end.join(", ")
114
+ "#{column} = \'#{send(column)}\'"
115
+ end.join(', ')
146
116
 
147
117
  Puffs::DBConnection.execute(<<-SQL)
148
118
  UPDATE
data/puffs.gemspec CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'puffs'
8
- spec.version = '0.2.05'
8
+ spec.version = '0.2.06'
9
9
  spec.authors = ['Zachary Moroni']
10
10
  spec.email = ['zachary.moroni@gmail.com']
11
11
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puffs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.05
4
+ version: 0.2.06
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Moroni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-25 00:00:00.000000000 Z
11
+ date: 2016-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -186,6 +186,7 @@ files:
186
186
  - lib/server_connection.rb
187
187
  - lib/session.rb
188
188
  - lib/sql_object/associatable.rb
189
+ - lib/sql_object/searchable.rb
189
190
  - lib/sql_object/sql_object.rb
190
191
  - puffs.gemspec
191
192
  - readme.md