puffs 0.2.04 → 0.2.05

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.
data/lib/relation.rb CHANGED
@@ -1,206 +1,208 @@
1
1
  require_relative './../lib/db_connection'
2
2
  require_relative 'sql_object/sql_object'
3
3
 
4
- class Puffs::SQLRelation
5
- def self.build_association(base, included, method_name)
6
- base.included_relations << included
4
+ module Puffs
5
+ class SQLRelation
6
+ def self.build_association(base, included, method_name)
7
+ base.included_relations << included
8
+
9
+ assoc_options = base.klass.assoc_options[method_name]
10
+ has_many = assoc_options.class == HasManyOptions
11
+
12
+ if has_many
13
+ i_send = assoc_options.foreign_key
14
+ b_send = assoc_options.primary_key
15
+ else
16
+ i_send = assoc_options.primary_key
17
+ b_send = assoc_options.foreign_key
18
+ end
7
19
 
8
- assoc_options = base.klass.assoc_options[method_name]
9
- has_many = assoc_options.class == HasManyOptions
20
+ match = proc do
21
+ selection = included.select do |i_sql_obj|
22
+ i_sql_obj.send(i_send) == self.send(b_send)
23
+ end
10
24
 
11
- if has_many
12
- i_send = assoc_options.foreign_key
13
- b_send = assoc_options.primary_key
14
- else
15
- i_send = assoc_options.primary_key
16
- b_send = assoc_options.foreign_key
17
- end
25
+ associated = has_many ? selection : selection.first
18
26
 
19
- match = proc do
20
- selection = included.select do |i_sql_obj|
21
- i_sql_obj.send(i_send) == self.send(b_send)
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).
29
+ new_match = proc { associated }
30
+ Puffs::SQLObject.define_singleton_method_by_proc(
31
+ self, method_name, new_match)
32
+
33
+ associated
22
34
  end
23
35
 
24
- associated = has_many ? selection : selection.first
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.
38
+ base.collection.each do |b_sql_obj|
39
+ Puffs::SQLObject.define_singleton_method_by_proc(
40
+ b_sql_obj, method_name, match)
41
+ end
42
+ end
25
43
 
26
- #After we find our values iteratively, we overwrite the method again
27
- #to the result values to reduce future lookup time to O(1).
28
- new_match = proc { associated }
29
- Puffs::SQLObject.define_singleton_method_by_proc(
30
- self, method_name, new_match)
44
+ attr_reader :klass, :collection, :loaded, :sql_count, :sql_limit
45
+ attr_accessor :included_relations
31
46
 
32
- associated
33
- end
47
+ def initialize(options)
48
+ defaults =
49
+ {
50
+ klass: nil,
51
+ loaded: false,
52
+ collection: []
53
+ }
34
54
 
35
- #we overwrite the association method for each SQLObject in the
36
- #collection so that it points to our cached relation and doesn't fire a query.
37
- base.collection.each do |b_sql_obj|
38
- Puffs::SQLObject.define_singleton_method_by_proc(
39
- b_sql_obj, method_name, match)
55
+ @klass = options[:klass]
56
+ @collection = options[:collection] || defaults[:collection]
57
+ @loaded = options[:loaded] || defaults[:loaded]
40
58
  end
41
- end
42
59
 
43
- attr_reader :klass, :collection, :loaded, :sql_count, :sql_limit
44
- attr_accessor :included_relations
60
+ def <<(item)
61
+ if item.class == klass
62
+ @collection << item
63
+ end
64
+ end
45
65
 
46
- def initialize(options)
47
- defaults =
48
- {
49
- klass: nil,
50
- loaded: false,
51
- collection: []
52
- }
66
+ def count
67
+ @sql_count = true
68
+ load
69
+ end
53
70
 
54
- @klass = options[:klass]
55
- @collection = options[:collection] || defaults[:collection]
56
- @loaded = options[:loaded] || defaults[:loaded]
57
- end
71
+ def included_relations
72
+ @included_relations ||= []
73
+ end
58
74
 
59
- def <<(item)
60
- if item.class == klass
61
- @collection << item
75
+ def includes(klass)
76
+ includes_params << klass
77
+ self
62
78
  end
63
- end
64
79
 
65
- def count
66
- @sql_count = true
67
- load
68
- end
80
+ def includes_params
81
+ @includes_params ||= []
82
+ end
69
83
 
70
- def included_relations
71
- @included_relations ||= []
72
- end
84
+ def limit(n)
85
+ @sql_limit = n
86
+ self
87
+ end
73
88
 
74
- def includes(klass)
75
- includes_params << klass
76
- self
77
- end
89
+ def load
90
+ if !loaded
91
+ puts "LOADING #{table_name}"
92
+ results = Puffs::DBConnection.execute(<<-SQL, sql_params[:values])
93
+ SELECT
94
+ #{sql_count ? "COUNT(*)" : self.table_name.to_s + ".*"}
95
+ FROM
96
+ #{self.table_name}
97
+ #{sql_params[:where]}
98
+ #{sql_params[:params]}
99
+ #{order_by_string}
100
+ #{"LIMIT #{sql_limit}" if sql_limit};
101
+ SQL
78
102
 
79
- def includes_params
80
- @includes_params ||= []
81
- end
103
+ results = sql_count ? results.first.values.first : parse_all(results)
104
+ end
82
105
 
83
- def limit(n)
84
- @sql_limit = n
85
- self
86
- end
106
+ results = results || self
87
107
 
88
- def load
89
- if !loaded
90
- puts "LOADING #{table_name}"
91
- results = DBConnection.execute(<<-SQL, sql_params[:values])
92
- SELECT
93
- #{sql_count ? "COUNT(*)" : self.table_name.to_s + ".*"}
94
- FROM
95
- #{self.table_name}
96
- #{sql_params[:where]}
97
- #{sql_params[:params]}
98
- #{order_by_string}
99
- #{"LIMIT #{sql_limit}" if sql_limit};
100
- SQL
108
+ unless includes_params.empty?
109
+ results = load_includes(results)
110
+ end
101
111
 
102
- results = sql_count ? results.first.values.first : parse_all(results)
112
+ results
103
113
  end
104
114
 
105
- results = results || self
115
+ def load_includes(relation)
116
+ 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
142
+ end
106
143
 
107
- unless includes_params.empty?
108
- results = load_includes(results)
144
+ relation
109
145
  end
110
146
 
111
- results
112
- end
147
+ def method_missing(method, *args, &block)
148
+ self.to_a.send(method, *args, &block)
149
+ end
113
150
 
114
- def load_includes(relation)
115
- includes_params.each do |param|
116
- if relation.klass.has_association?(param)
117
- puts "LOADING #{param.to_s}"
118
- assoc = klass.assoc_options[param]
119
- f_k = assoc.foreign_key
120
- p_k = assoc.primary_key
121
- includes_table = assoc.table_name.to_s
122
- in_ids = relation.collection.map do |sqlobject|
123
- sqlobject.id
124
- end.join(", ")
125
-
126
- has_many = assoc.class == HasManyOptions
127
-
128
- results = DBConnection.execute(<<-SQL)
129
- SELECT
130
- #{includes_table}.*
131
- FROM
132
- #{includes_table}
133
- WHERE
134
- #{includes_table}.#{has_many ? f_k : p_k}
135
- IN
136
- (#{in_ids});
137
- SQL
138
- included = assoc.model_class.parse_all(results)
139
- Puffs::SQLRelation.build_association(relation, included, param)
151
+ def order(params)
152
+ if params.is_a?(Hash)
153
+ order_params_hash.merge!(params)
154
+ else
155
+ order_params_hash.merge!(params => :asc)
140
156
  end
157
+ self
141
158
  end
142
159
 
143
- relation
144
- end
145
-
146
- def method_missing(method, *args, &block)
147
- self.to_a.send(method, *args, &block)
148
- end
149
-
150
- def order(params)
151
- if params.is_a?(Hash)
152
- order_params_hash.merge!(params)
153
- else
154
- order_params_hash.merge!(params => :asc)
160
+ def order_params_hash
161
+ @order_params_hash ||= {}
155
162
  end
156
- self
157
- end
158
163
 
159
- def order_params_hash
160
- @order_params_hash ||= {}
161
- end
164
+ def order_by_string
165
+ hash_string = order_params_hash.map do |column, asc_desc|
166
+ "#{column} #{asc_desc.to_s.upcase}"
167
+ end.join(", ")
162
168
 
163
- def order_by_string
164
- hash_string = order_params_hash.map do |column, asc_desc|
165
- "#{column} #{asc_desc.to_s.upcase}"
166
- end.join(", ")
169
+ hash_string.empty? ? "" : "ORDER BY #{hash_string}"
170
+ end
167
171
 
168
- hash_string.empty? ? "" : "ORDER BY #{hash_string}"
169
- end
172
+ def parse_all(attributes)
173
+ klass.parse_all(attributes).where(where_params_hash).includes(includes_params)
174
+ end
170
175
 
171
- def parse_all(attributes)
172
- klass.parse_all(attributes).where(where_params_hash).includes(includes_params)
173
- end
176
+ def sql_params
177
+ params, values = [], []
174
178
 
175
- def sql_params
176
- params, values = [], []
179
+ i = 1
180
+ where_params_hash.map do |attribute, value|
181
+ params << "#{attribute} = $#{i}"
182
+ values << value
183
+ i += 1
184
+ end
177
185
 
178
- i = 1
179
- where_params_hash.map do |attribute, value|
180
- params << "#{attribute} = $#{i}"
181
- values << value
182
- i += 1
186
+ { params: params.join(" AND "),
187
+ where: params.empty? ? nil : "WHERE",
188
+ values: values }
183
189
  end
184
190
 
185
- { params: params.join(" AND "),
186
- where: params.empty? ? nil : "WHERE",
187
- values: values }
188
- end
189
-
190
- def table_name
191
- klass.table_name
192
- end
191
+ def table_name
192
+ klass.table_name
193
+ end
193
194
 
194
- def to_a
195
- self.load.collection
196
- end
195
+ def to_a
196
+ self.load.collection
197
+ end
197
198
 
198
- def where_params_hash
199
- @where_params_hash ||= {}
200
- end
199
+ def where_params_hash
200
+ @where_params_hash ||= {}
201
+ end
201
202
 
202
- def where(params)
203
- where_params_hash.merge!(params)
204
- self
203
+ def where(params)
204
+ where_params_hash.merge!(params)
205
+ self
206
+ end
205
207
  end
206
208
  end
data/lib/router.rb CHANGED
@@ -1,74 +1,78 @@
1
- class Route
2
- attr_reader :pattern, :http_method, :controller_class, :action_name
1
+ module Puffs
2
+ # The Puffs Router.
3
+ class Router
4
+ attr_reader :routes
3
5
 
4
- def initialize(pattern, http_method, controller_class, action_name)
5
- @pattern = pattern
6
- @http_method = http_method
7
- @controller_class = controller_class
8
- @action_name = action_name
9
- end
10
-
11
- # checks if pattern matches path and method matches request method
12
- def matches?(req)
13
- pattern =~ req.path && req.request_method == http_method.to_s.upcase
14
- end
15
-
16
- # use pattern to pull out route params (save for later?)
17
- # instantiate controller and call controller action
18
- def run(req, res)
19
- matches = pattern.match(req.path)
20
- route_params = {}
6
+ def initialize
7
+ @routes = []
8
+ end
21
9
 
22
- matches.names.each do |name|
23
- route_params[name] = matches[name]
10
+ # Adds a new route to the list of routes
11
+ def add_route(pattern, method, controller_class, action_name)
12
+ routes << Route.new(pattern, method, controller_class, action_name)
24
13
  end
25
14
 
26
- controller_class.new(req, res, route_params).invoke_action(action_name)
27
- end
28
- end
15
+ # evaluate the proc in the context of the instance
16
+ # for syntactic sugar :)
17
+ def draw(&proc)
18
+ instance_eval(&proc)
19
+ end
29
20
 
30
- class Router
31
- attr_reader :routes
21
+ # make each of these methods that
22
+ # when called add route
23
+ [:get, :post, :put, :delete].each do |http_method|
24
+ define_method(http_method) do |pattern, controller_class, action_name|
25
+ add_route(pattern, http_method, controller_class, action_name)
26
+ end
27
+ end
32
28
 
33
- def initialize
34
- @routes = []
35
- end
29
+ # should return the route that matches this request
30
+ def match(req)
31
+ routes.each do |route|
32
+ return route if route.matches?(req)
33
+ end
34
+ nil
35
+ end
36
36
 
37
- # simply adds a new route to the list of routes
38
- def add_route(pattern, method, controller_class, action_name)
39
- routes << Route.new(pattern, method, controller_class, action_name)
37
+ # either throw 404 or call run on a matched route
38
+ def run(req, res)
39
+ route = match(req)
40
+ if route
41
+ route.run(req, res)
42
+ else
43
+ res.status = 404
44
+ res.body = ["Sorry, Charlie. That page doesn't exist."]
45
+ end
46
+ end
40
47
  end
41
48
 
42
- # evaluate the proc in the context of the instance
43
- # for syntactic sugar :)
44
- def draw(&proc)
45
- instance_eval(&proc)
46
- end
49
+ # Router is comprised of Routes.
50
+ class Route
51
+ attr_reader :pattern, :http_method, :controller_class, :action_name
47
52
 
48
- # make each of these methods that
49
- # when called add route
50
- [:get, :post, :put, :delete].each do |http_method|
51
- define_method(http_method) do |pattern, controller_class, action_name|
52
- add_route(pattern, http_method, controller_class, action_name)
53
+ def initialize(pattern, http_method, controller_class, action_name)
54
+ @pattern = pattern
55
+ @http_method = http_method
56
+ @controller_class = controller_class
57
+ @action_name = action_name
53
58
  end
54
- end
55
59
 
56
- # should return the route that matches this request
57
- def match(req)
58
- routes.each do |route|
59
- return route if route.matches?(req)
60
+ # checks if pattern matches path and method matches request method
61
+ def matches?(req)
62
+ pattern =~ req.path && req.request_method == http_method.to_s.upcase
60
63
  end
61
- nil
62
- end
63
64
 
64
- # either throw 404 or call run on a matched route
65
- def run(req, res)
66
- route = match(req)
67
- if route
68
- route.run(req, res)
69
- else
70
- res.status = 404
71
- res.body = ["Sorry, Charlie. That page doesn't exist."]
65
+ # use pattern to pull out route params (save for later?)
66
+ # instantiate controller and call controller action
67
+ def run(req, res)
68
+ matches = pattern.match(req.path)
69
+ route_params = {}
70
+
71
+ matches.names.each do |name|
72
+ route_params[name] = matches[name]
73
+ end
74
+
75
+ controller_class.new(req, res, route_params).invoke_action(action_name)
72
76
  end
73
77
  end
74
78
  end
@@ -1,18 +1,21 @@
1
1
  require 'rack'
2
2
  require './config/routes'
3
3
 
4
- class ServerConnection
5
- def self.start
6
- app = Proc.new do |env|
7
- req = Rack::Request.new(env)
8
- res = Rack::Response.new
9
- ROUTER.run(req, res)
10
- res.finish
11
- end
4
+ module Puffs
5
+ # Invoked through `puffs server` in CLI.
6
+ class ServerConnection
7
+ def self.start
8
+ app = proc do |env|
9
+ req = Rack::Request.new(env)
10
+ res = Rack::Response.new
11
+ ROUTER.run(req, res)
12
+ res.finish
13
+ end
12
14
 
13
- Rack::Server.start(
14
- app: app,
15
- Port: 3000
16
- )
15
+ Rack::Server.start(
16
+ app: app,
17
+ Port: 3000
18
+ )
19
+ end
17
20
  end
18
21
  end
data/lib/session.rb CHANGED
@@ -1,28 +1,36 @@
1
1
  require 'json'
2
2
 
3
- class Session
4
- # find the cookie for this app
5
- # deserialize the cookie into a hash
6
- def initialize(req)
7
- cookie = req.cookies['_rails_lite_app']
8
- if cookie
9
- @session_data = JSON.parse(cookie)
10
- else
11
- @session_data = {}
3
+ module Puffs
4
+ # Session token.
5
+ class Session
6
+ # find the cookie for this app
7
+ # deserialize the cookie into a hash
8
+ def initialize(req)
9
+ cookie = req.cookies['_rails_lite_app']
10
+
11
+ if cookie
12
+ @session_data = JSON.parse(cookie)
13
+ else
14
+ @session_data = {}
15
+ end
12
16
  end
13
- end
14
17
 
15
- def [](key)
16
- @session_data[key]
17
- end
18
+ def [](key)
19
+ @session_data[key]
20
+ end
18
21
 
19
- def []=(key, val)
20
- @session_data[key] = val
21
- end
22
+ def []=(key, val)
23
+ @session_data[key] = val
24
+ end
22
25
 
23
- # serialize the hash into json and save in a cookie
24
- # add to the responses cookies
25
- def store_session(res)
26
- res.set_cookie("_rails_lite_app", { path: '/', value: @session_data.to_json })
26
+ # serialize the hash into json and save in a cookie
27
+ # add to the responses cookies
28
+ def store_session(res)
29
+ res.set_cookie(
30
+ '_rails_lite_app',
31
+ path: '/',
32
+ value: @session_data.to_json
33
+ )
34
+ end
27
35
  end
28
36
  end