puffs 0.2.05 → 0.2.06

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