grippy-doozer 0.1.0
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +57 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/bin/doozer +8 -0
- data/doozer.gemspec +114 -0
- data/lib/doozer/README.rb +40 -0
- data/lib/doozer/active_support/array.rb +14 -0
- data/lib/doozer/active_support/class.rb +221 -0
- data/lib/doozer/active_support/date_time.rb +23 -0
- data/lib/doozer/active_support/object.rb +43 -0
- data/lib/doozer/active_support/time.rb +32 -0
- data/lib/doozer/app.rb +265 -0
- data/lib/doozer/configs.rb +131 -0
- data/lib/doozer/controller.rb +335 -0
- data/lib/doozer/extend.rb +10 -0
- data/lib/doozer/initializer.rb +95 -0
- data/lib/doozer/lib.rb +32 -0
- data/lib/doozer/logger.rb +11 -0
- data/lib/doozer/orm/active_record.rb +19 -0
- data/lib/doozer/orm/data_mapper.rb +19 -0
- data/lib/doozer/orm/sequel.rb +18 -0
- data/lib/doozer/partial.rb +99 -0
- data/lib/doozer/plugins/paginate/init.rb +2 -0
- data/lib/doozer/plugins/paginate/lib/paginate/collection.rb +60 -0
- data/lib/doozer/plugins/paginate/lib/paginate/finder.rb +116 -0
- data/lib/doozer/plugins/paginate/lib/paginate/view_helpers.rb +37 -0
- data/lib/doozer/plugins/paginate/lib/paginate.rb +32 -0
- data/lib/doozer/rackup/server.ru +37 -0
- data/lib/doozer/rackup/test.rb +19 -0
- data/lib/doozer/redirect.rb +12 -0
- data/lib/doozer/route.rb +264 -0
- data/lib/doozer/scripts/cluster.rb +132 -0
- data/lib/doozer/scripts/migrate.rb +108 -0
- data/lib/doozer/scripts/task.rb +60 -0
- data/lib/doozer/scripts/test.rb +23 -0
- data/lib/doozer/version.rb +8 -0
- data/lib/doozer/view_helpers.rb +163 -0
- data/lib/doozer/watcher.rb +375 -0
- data/lib/doozer.rb +30 -0
- data/lib/generator/generator.rb +547 -0
- data/templates/skeleton/Rakefile +3 -0
- data/templates/skeleton/app/controllers/application_controller.rb +2 -0
- data/templates/skeleton/app/controllers/index_controller.rb +7 -0
- data/templates/skeleton/app/helpers/application_helper.rb +17 -0
- data/templates/skeleton/app/views/global/_header.html.erb +7 -0
- data/templates/skeleton/app/views/global/_navigation.html.erb +6 -0
- data/templates/skeleton/app/views/index/index.html.erb +108 -0
- data/templates/skeleton/app/views/layouts/default.html.erb +23 -0
- data/templates/skeleton/config/app.yml +31 -0
- data/templates/skeleton/config/database.yml +25 -0
- data/templates/skeleton/config/environment.rb +13 -0
- data/templates/skeleton/config/rack.rb +30 -0
- data/templates/skeleton/config/routes.rb +69 -0
- data/templates/skeleton/script/cluster +5 -0
- data/templates/skeleton/script/migrate +5 -0
- data/templates/skeleton/script/task +5 -0
- data/templates/skeleton/script/test +4 -0
- data/templates/skeleton/static/404.html +16 -0
- data/templates/skeleton/static/500.html +16 -0
- data/templates/skeleton/static/css/style.css +32 -0
- data/templates/skeleton/static/favicon.ico +0 -0
- data/templates/skeleton/static/js/application.js +1 -0
- data/templates/skeleton/static/js/jquery-1.3.min.js +19 -0
- data/templates/skeleton/static/robots.txt +5 -0
- data/templates/skeleton/test/fixtures/setup.rb +6 -0
- data/templates/skeleton/test/setup.rb +33 -0
- data/test/doozer_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +126 -0
@@ -0,0 +1,335 @@
|
|
1
|
+
# load gems
|
2
|
+
%w(rack erb).each { |dep| require dep }
|
3
|
+
|
4
|
+
# load doozer modules
|
5
|
+
# %w(doozer/lib doozer/extend doozer/logger doozer/view_helpers doozer/route doozer/partial).each { |dep| require dep }
|
6
|
+
|
7
|
+
# autoload all models
|
8
|
+
# Dir.glob(File.join(File.dirname(__FILE__),'../app/models/*.rb')).each {|f| require f }
|
9
|
+
|
10
|
+
module Doozer
|
11
|
+
|
12
|
+
# This is the main Controller class which is inherited by application controllers.
|
13
|
+
#
|
14
|
+
# Controllers have access to all ViewHelpers.
|
15
|
+
class Controller
|
16
|
+
|
17
|
+
# @route variable containing the route instance
|
18
|
+
attr_accessor :route
|
19
|
+
# @env variable passed from the Rack request
|
20
|
+
attr_accessor :env
|
21
|
+
# @request variable. See Rack request for additional methods. http://rack.rubyforge.org/doc/Rack/Request.html
|
22
|
+
attr_accessor :request
|
23
|
+
# @params variable which is a symbolized hash of all querystring values
|
24
|
+
attr_accessor :params
|
25
|
+
# @flash variable containing a hash of strings which are persisted in the flash cookie across the response, next request/response and then removed.
|
26
|
+
attr_accessor :flash
|
27
|
+
# @session variable containing a hash of strings which are persisted in the session cookie until the browser session expires.
|
28
|
+
attr_accessor :session
|
29
|
+
# @view variable containing a hash of string which are read from layouts.
|
30
|
+
attr_accessor :view
|
31
|
+
# @bust_key variable which is appended to img sources and script sources via view_helpers in development mode
|
32
|
+
attr_accessor :bust_key
|
33
|
+
# @format variable which is a symbol
|
34
|
+
attr_accessor :format
|
35
|
+
# @port variable holing the port number of the appserver handling the request
|
36
|
+
attr_accessor :port
|
37
|
+
# @render_args variable containing a hash of values to use while rendering the request
|
38
|
+
attr_accessor :render_args
|
39
|
+
|
40
|
+
include Doozer::Util::Logger
|
41
|
+
include Doozer::ViewHelpers
|
42
|
+
|
43
|
+
self.class_inheritable_accessor :after_initialize_exclude, :before_filter_exclude, :after_filter_exclude, :require_view_helpers
|
44
|
+
|
45
|
+
# Array of actions to exclude from calling after_initialize.
|
46
|
+
#
|
47
|
+
# Example: self.after_initialize_exclude=[:action_1, :action_2]
|
48
|
+
self.after_initialize_exclude=[]
|
49
|
+
|
50
|
+
# Array of actions to exclude from calling before_filter.
|
51
|
+
#
|
52
|
+
# Example: self.before_filter_exclude=[:action_1, :action_2]
|
53
|
+
self.before_filter_exclude=[]
|
54
|
+
|
55
|
+
# Array of actions to exclude from calling after_filter.
|
56
|
+
#
|
57
|
+
# Example: self.after_filter_exclude=[:action_1, :action_2]
|
58
|
+
self.after_filter_exclude=[]
|
59
|
+
|
60
|
+
# Array of actions to exclude from calling require_view.
|
61
|
+
#
|
62
|
+
# Example: self.require_view_helpers=[:application, :helper_1]
|
63
|
+
self.require_view_helpers=[]
|
64
|
+
|
65
|
+
# When a Controller is intialized it expects the following args:
|
66
|
+
#
|
67
|
+
# args={
|
68
|
+
# :route=>route matched against the request path,
|
69
|
+
# :extra_params=>the route tokens parameterized as a hash,
|
70
|
+
# :port=>the port of the appserver responding to the request
|
71
|
+
# }
|
72
|
+
#
|
73
|
+
# * :extra_params are turned into instance variables so you can access them directly from controller methods and views. In order to keep a small footprint these aren't passed into partial classes.
|
74
|
+
#
|
75
|
+
# Example: A route of /admin/post/:id and a request path of /admin/post/8 automatically exposes an instance variable of @id with a value of 8 in your controller.
|
76
|
+
#
|
77
|
+
# * query params are accessible via @params hash and are parameterized via Rack.
|
78
|
+
|
79
|
+
def initialize(args={})
|
80
|
+
@route = args[:route]; @env = args[:env]
|
81
|
+
@format = @route.format
|
82
|
+
@port = args[:port]
|
83
|
+
|
84
|
+
#init request from env
|
85
|
+
@request = Rack::Request.new(@env)
|
86
|
+
|
87
|
+
#holds all variables for template binding
|
88
|
+
@view={}; @view[:meta]={}
|
89
|
+
|
90
|
+
#store flash
|
91
|
+
@flash={}; flash_from_cookie()
|
92
|
+
|
93
|
+
#store session
|
94
|
+
@session={}; session_from_cookie()
|
95
|
+
|
96
|
+
#symbolize params
|
97
|
+
@params={}; @request.params.each { |key, value| @params[key.to_sym] = value}
|
98
|
+
|
99
|
+
#set bust key
|
100
|
+
@bust_key = (rand(1000) * 1024)
|
101
|
+
|
102
|
+
# set up default render_args
|
103
|
+
@render_args = {:layout=>nil, :view=>nil, :text=>nil}
|
104
|
+
render_args_init()
|
105
|
+
|
106
|
+
#turn extra params into instance variables...
|
107
|
+
args[:extra_params].each { |key, value| self.instance_variable_set("@#{key}".to_sym, value)}
|
108
|
+
logger.info(" Params: #{@request.params.inspect}") if not @request.params.nil?
|
109
|
+
logger.info(" Extra params: #{args[:extra_params].inspect}") if not args[:extra_params].nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
# Renders an action with any of the following overridable parameters:
|
113
|
+
#
|
114
|
+
# args={
|
115
|
+
# :view=>Symbol, String or ERB,
|
116
|
+
# :layout=>Symbol,
|
117
|
+
# :text=>'this is the text to render'
|
118
|
+
# }
|
119
|
+
#
|
120
|
+
# :view - All actions default to a view of views/controller_name/action_name.format.erb which is originated from the route properties.
|
121
|
+
#
|
122
|
+
# To override this from controller actions, you can pass any of the following:
|
123
|
+
#
|
124
|
+
# * :view=>:view_name
|
125
|
+
#
|
126
|
+
# This assumes the view is in the same controller as the present action.
|
127
|
+
#
|
128
|
+
# * :view=>'controller_name/action_name'
|
129
|
+
#
|
130
|
+
# This renders a view from a the provided controller and action and with the format specified in the route.
|
131
|
+
#
|
132
|
+
# * :view=>ERB.new('<%=var%> is nice')
|
133
|
+
#
|
134
|
+
# :layout - All actions default to a layout of views/layouts/default.format.erb
|
135
|
+
#
|
136
|
+
# To override this from controller actions, you can pass any of the following:
|
137
|
+
#
|
138
|
+
# * :layout=>:layout_name_format or :none (don't display a layout at all)
|
139
|
+
#
|
140
|
+
# There is no need to specify the format for :html formats.
|
141
|
+
#
|
142
|
+
# Example: :layout=>:some_layout (where format equals :html) or :some_layout_json (where format equals :json)
|
143
|
+
#
|
144
|
+
# :text - Overrides all view rendering options and displays an ERB template with the provided text string.
|
145
|
+
#
|
146
|
+
# A layout is rendered unless its overriden or the route was declared without one.
|
147
|
+
#
|
148
|
+
# To override this from controller actions, you can pass any of the following:
|
149
|
+
def render(args={})
|
150
|
+
change_layout(args[:layout]) if args[:layout]
|
151
|
+
change_view(args[:view]) if args[:view]
|
152
|
+
change_view(ERB.new(args[:text])) if args[:text]
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
# This method is called from the appserver controller handler.
|
157
|
+
def render_result
|
158
|
+
layout = @render_args[:layout]
|
159
|
+
view = @render_args[:view]
|
160
|
+
if layout.kind_of? Symbol # this handles the layout(:none)
|
161
|
+
view.result(binding)
|
162
|
+
else
|
163
|
+
@view[:timestamp] = "<!-- server: #{@port} / rendered: #{Time.now()} / env: #{rack_env} -->"
|
164
|
+
@view[:body] = view.result(binding)
|
165
|
+
# layout = @layout if layout.nil? # this handles the layout(:some_other_layout) case for formats
|
166
|
+
layout.result(binding)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# A method to render a partial from a controller. Expects a file name and optional local variables. See Partial for more details.
|
171
|
+
#
|
172
|
+
# By default, the @request variable is appended to locals and available in the partial view.
|
173
|
+
def partial(file=nil, locals={})
|
174
|
+
# self.instance_variables.each { | k |
|
175
|
+
# locals[k.gsub(/@/,'').to_s] = eval(k)
|
176
|
+
# }
|
177
|
+
# p locals.inspect
|
178
|
+
locals[:request] = @request
|
179
|
+
Doozer::Partial.partial(file, locals, route=@route)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Redirect the response object to the tokenized route url with optional query string values
|
183
|
+
#
|
184
|
+
# The route is passed through the ViewHelpers.url method. See url() for examples.
|
185
|
+
def redirect_to(route={}, opts={})
|
186
|
+
path = url(route)
|
187
|
+
# p "Redirect to: #{path}"
|
188
|
+
raise Doozer::Redirect.new(path, opts)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Sequel ORM db connection
|
192
|
+
def db
|
193
|
+
Doozer::Configs.db_conn
|
194
|
+
end
|
195
|
+
|
196
|
+
# Compile flash keys as name=value array which are stored in the flash cookie. The flash variables are only persisted for one response.
|
197
|
+
def flash_to_cookie
|
198
|
+
#loop over all flash messages and return as name/value array
|
199
|
+
out=[]; @flash.each { |key, value| out.push("#{key}=#{CGI::escape(value.to_s)}") }
|
200
|
+
return out
|
201
|
+
end
|
202
|
+
|
203
|
+
# Read all the flash cookies and store them in the @flash instance variable
|
204
|
+
def flash_from_cookie
|
205
|
+
#split name/value pairs and merge with flash
|
206
|
+
if @request.cookies
|
207
|
+
if @request.cookies["flash"]
|
208
|
+
pairs=@request.cookies["flash"].split('&')
|
209
|
+
pairs.each{|pair|
|
210
|
+
pair = pair.split('=')
|
211
|
+
@flash[pair[0].to_sym]=CGI::unescape(pair[1])
|
212
|
+
}
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Compile session keys as name=value array which are eventually stored as cookies.
|
218
|
+
def session_to_cookie
|
219
|
+
#loop over all flash messages and return as name/value array
|
220
|
+
out=[]; @session.each { |key, value| out.push("#{key}=#{CGI::escape(value.to_s)}") }
|
221
|
+
return out
|
222
|
+
end
|
223
|
+
|
224
|
+
# Read all the session cookies and store them in the @session instance variable
|
225
|
+
def session_from_cookie
|
226
|
+
#split name/value pairs and merge with flash
|
227
|
+
if @request.cookies
|
228
|
+
if @request.cookies["session"]
|
229
|
+
pairs=@request.cookies["session"].split('&')
|
230
|
+
pairs.each{|pair|
|
231
|
+
pair = pair.split('=')
|
232
|
+
@session[pair[0].to_sym]=CGI::unescape(pair[1])
|
233
|
+
}
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# Method for setting metatags via Controllers.
|
239
|
+
#
|
240
|
+
# Pass an options hash to meta and all the keys are turned into metatags with the corresponding values.
|
241
|
+
#
|
242
|
+
# Example: meta({:description=>'The awesome metatag description is awesome', :keywords=>'awesome, blog, of awesomeness'})
|
243
|
+
def meta(opt={})
|
244
|
+
@view[:meta]=opt
|
245
|
+
end
|
246
|
+
|
247
|
+
# DEPRECATED: use render() instead
|
248
|
+
def layout(sym)
|
249
|
+
raise "Deprecated: Controller#layout; Use render({:layout=>:symbol}) instead"
|
250
|
+
end
|
251
|
+
|
252
|
+
# Controller hook called after controller#initialize call.
|
253
|
+
#
|
254
|
+
# By default, this method automatically checks if the authtoken is present for post requests. It throws an error if it's missing or has been tampered with.
|
255
|
+
def after_initialize
|
256
|
+
# test if request == post and if so if authtoken is present and valid
|
257
|
+
if @request.post?
|
258
|
+
token=@params[:_authtoken]
|
259
|
+
if token
|
260
|
+
raise "Doozer Authtoken Tampered With!" if not authtoken_matches?(token)
|
261
|
+
else
|
262
|
+
raise "Doozer Authtoken Missing! By default, post requests require an authtoken. You can override this by adding the action to the after_initialize_exclude list." if not authtoken_matches?(token)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Controller hook called before controller#method call
|
268
|
+
def before_filter; end
|
269
|
+
|
270
|
+
# Controller hook called after controller#method call
|
271
|
+
def after_filter; end
|
272
|
+
|
273
|
+
# Include additional view helpers declared for the class.
|
274
|
+
#
|
275
|
+
# This method automatically appends '_helper' to each required helper symbol
|
276
|
+
def self.include_view_helpers
|
277
|
+
# importing view helpers into controller
|
278
|
+
self.require_view_helpers.each { | sym |
|
279
|
+
self.include_view_helper("#{sym.to_s}_helper")
|
280
|
+
}
|
281
|
+
end
|
282
|
+
|
283
|
+
# Include the app/helpers file_name. Expects helper as a string.
|
284
|
+
#
|
285
|
+
# You must pass the full file name if you use this method.
|
286
|
+
#
|
287
|
+
# Example: self.include_view_helper('application_helper')
|
288
|
+
def self.include_view_helper(helper)
|
289
|
+
# importing view helpers into controller
|
290
|
+
include Object.const_get(Doozer::Lib.classify("#{helper}"))
|
291
|
+
end
|
292
|
+
|
293
|
+
private
|
294
|
+
def render_args_init
|
295
|
+
if not [301, 302].include?(@route.status)
|
296
|
+
# view = (@format == :html) ? "#{@route.name.to_s}_html".to_sym : @route.
|
297
|
+
view = @route.view.to_sym
|
298
|
+
layout = (@route.layout.kind_of? String) ? @route.layout.to_sym : @route.layout
|
299
|
+
render({
|
300
|
+
:view=>view,
|
301
|
+
:layout=>layout
|
302
|
+
})
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def change_layout(sym)
|
307
|
+
if sym == :none
|
308
|
+
layout=sym
|
309
|
+
else
|
310
|
+
#this needs to look up the layout and reset layout to this erb template
|
311
|
+
lay = Doozer::App.layouts[sym]
|
312
|
+
raise "Can't find layout for #{sym}" if lay.nil?
|
313
|
+
layout = lay
|
314
|
+
end
|
315
|
+
@render_args[:layout] = layout
|
316
|
+
end
|
317
|
+
|
318
|
+
def change_view(args)
|
319
|
+
if args.kind_of? Symbol
|
320
|
+
# implies we're using the same controller as the current controller with a view name of :view_name
|
321
|
+
view = Doozer::App.views[@route.controller.to_sym][args]
|
322
|
+
elsif args.kind_of? String
|
323
|
+
# implies
|
324
|
+
controller = (args.index('/')) ? args.split('/')[0].to_sym : @route.controller.to_sym
|
325
|
+
action = (args.index('/')) ? args.split('/')[1] : args
|
326
|
+
action = "#{action}_#{@format.to_s}".to_sym
|
327
|
+
view = Doozer::App.views[controller][action]
|
328
|
+
elsif args.kind_of? ERB
|
329
|
+
view = args
|
330
|
+
end
|
331
|
+
view = ERB.new("Missing view for controller#action") if view.nil?
|
332
|
+
@render_args[:view] = view
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#
|
2
|
+
# Load some of the rails active_support/core_ext class extensions which are used by Doozer.
|
3
|
+
# All of these are automtically loaded if active_record is used but we need to provide them incase
|
4
|
+
#
|
5
|
+
require 'doozer/active_support/array'
|
6
|
+
require 'doozer/active_support/object'
|
7
|
+
require 'doozer/active_support/class'
|
8
|
+
require 'doozer/active_support/time'
|
9
|
+
require 'doozer/active_support/date_time'
|
10
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Doozer
|
2
|
+
|
3
|
+
# This is the main class which facilitates booting Doozer components and hooks.
|
4
|
+
#
|
5
|
+
# Calling boot initializes Doozer in the following order:
|
6
|
+
# 1. Doozer::Configs
|
7
|
+
# 2. require ORM
|
8
|
+
# 3. require root/config/environment.rb
|
9
|
+
# 4. call after_orm_init
|
10
|
+
# 5. require Doozer::App
|
11
|
+
# 6. call before_rackup_init
|
12
|
+
class Initializer
|
13
|
+
@@after_orm = []
|
14
|
+
@@before_rackup = []
|
15
|
+
|
16
|
+
# env - :development, :deployment, or :test
|
17
|
+
def self.boot(env)
|
18
|
+
#--load configs
|
19
|
+
require 'doozer/configs'
|
20
|
+
Doozer::Configs.load(env)
|
21
|
+
|
22
|
+
#--load orm
|
23
|
+
Doozer::Initializer.orm
|
24
|
+
|
25
|
+
#--load environment hooks
|
26
|
+
Doozer::Initializer.environment
|
27
|
+
|
28
|
+
#--call the after_orm_init features
|
29
|
+
Doozer::Initializer.after_orm_init
|
30
|
+
|
31
|
+
#--load app
|
32
|
+
require 'doozer/app'
|
33
|
+
|
34
|
+
#--call the before_rackup_init features
|
35
|
+
Doozer::Initializer.before_rackup_init
|
36
|
+
end
|
37
|
+
|
38
|
+
# Checks to see if an ORM gem (active_record, data_mapper, or sequel) is specified in database.yml and loads it.
|
39
|
+
def self.orm
|
40
|
+
begin
|
41
|
+
# load orm layer (if required)
|
42
|
+
if not Doozer::Configs.orm.nil? and not Doozer::Configs.db.nil?
|
43
|
+
require "doozer/orm/#{Doozer::Configs.orm}"
|
44
|
+
Doozer::ORM.load
|
45
|
+
end
|
46
|
+
rescue => e
|
47
|
+
Doozer::Configs.logger.error(e)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Requires the root/config/environment.rb hooks.
|
52
|
+
#
|
53
|
+
# This is where you can place your code to initialize additional plugins for models, extend ruby, or whatever else yor app requires.
|
54
|
+
#
|
55
|
+
#=== Example environment.rb
|
56
|
+
# Time::DATE_FORMATS[:month_and_year] = "%B %Y"
|
57
|
+
#
|
58
|
+
# Doozer::Initializer.after_orm do | config |
|
59
|
+
# p "Extending some ORM, yo!"
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# Doozer::Initializer.before_rackup do | config |
|
63
|
+
# p "Before rackup, horray for rackup!"
|
64
|
+
# end
|
65
|
+
def self.environment
|
66
|
+
begin
|
67
|
+
require "#{Dir.pwd}/config/environment"
|
68
|
+
rescue => e
|
69
|
+
Doozer::Configs.logger.error(e)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Primary hook for extending/overriding ORM. Code block is pushed onto an array which allows for multiple hooks throughtout different files.
|
74
|
+
#
|
75
|
+
# &block - code to execute after ORM is intialized
|
76
|
+
def self.after_orm(&block)
|
77
|
+
@@after_orm.push(block) if block_given?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Primary hook for adding/overriding Doozer::ViewHelpers methods. Code block is pushed onto an array which allows for multiple hooks throughtout different files.
|
81
|
+
#
|
82
|
+
# &block - code to execute after prior to Doozer.App.new being intialized.
|
83
|
+
def self.before_rackup(&block)
|
84
|
+
@@before_rackup.push(block) if block_given?
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
def self.after_orm_init
|
89
|
+
@@after_orm.each{ | block | instance_eval(&block)}
|
90
|
+
end
|
91
|
+
def self.before_rackup_init
|
92
|
+
@@before_rackup.each{ | block | instance_eval(&block)}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/doozer/lib.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Doozer
|
2
|
+
class Lib
|
3
|
+
|
4
|
+
#Return a ClassName as string from an underscored string.
|
5
|
+
# example: input "example_class" > "ExampleClass"
|
6
|
+
def self.classify(klass)
|
7
|
+
if klass.index('_')
|
8
|
+
klass = klass.split('_')
|
9
|
+
parts = []
|
10
|
+
klass = klass.each { | part |
|
11
|
+
parts.push(part.capitalize)
|
12
|
+
}
|
13
|
+
klass = parts.join('')
|
14
|
+
else
|
15
|
+
klass.capitalize!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#Returns a one-level deep folder/file structure and preservers underscores for filename.
|
20
|
+
# example: input "folder_some_file_name" > "folder/some_file_name"
|
21
|
+
def self.pathify_first(s)
|
22
|
+
if s.index('_')
|
23
|
+
parts = s.split('_')
|
24
|
+
folder = parts[0]
|
25
|
+
file = parts.slice(1, parts.length).join('_')
|
26
|
+
s = "#{folder}/#{file}"
|
27
|
+
end
|
28
|
+
s
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
module Doozer
|
3
|
+
module ORM
|
4
|
+
def self.load
|
5
|
+
db_config = Doozer::Configs.db()
|
6
|
+
# ActiveRecord::Base.allow_concurrency = true
|
7
|
+
ActiveRecord::Base.establish_connection(
|
8
|
+
:adapter => db_config["adapter"],
|
9
|
+
:host => db_config["host"],
|
10
|
+
:username => db_config["username"],
|
11
|
+
:password => db_config["password"],
|
12
|
+
:database => db_config["database"]
|
13
|
+
)
|
14
|
+
p "ORM: #{Doozer::Configs.orm()} initialized..."
|
15
|
+
p "ORM: logging initialized"
|
16
|
+
ActiveRecord::Base.logger = Doozer::Configs.logger
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
module Doozer
|
3
|
+
|
4
|
+
# See for more info => http://datamapper.org/doku.php?id=getting_started_with_datamapper
|
5
|
+
module ORM
|
6
|
+
def self.load
|
7
|
+
db_config = Doozer::Configs.db()
|
8
|
+
DataMapper.setup(:default, {
|
9
|
+
:adapter => db_config["adapter"],
|
10
|
+
:database => db_config["database"],
|
11
|
+
:username => db_config["username"],
|
12
|
+
:password => db_config["password"],
|
13
|
+
:host => db_config["host"]
|
14
|
+
})
|
15
|
+
p "ORM: #{Doozer::Configs.orm()} initialized..."
|
16
|
+
DataMapper::Logger.new(STDOUT, :debug)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
module Doozer
|
3
|
+
module ORM
|
4
|
+
|
5
|
+
# See for details => http://sequel.rubyforge.org/rdoc/index.html
|
6
|
+
def self.load
|
7
|
+
db_config = Doozer::Configs.db()
|
8
|
+
Doozer::Configs.db_conn = Sequel.connect({
|
9
|
+
:adapter => db_config["adapter"],
|
10
|
+
:database => db_config["database"],
|
11
|
+
:username => db_config["username"],
|
12
|
+
:password => db_config["password"],
|
13
|
+
:host => db_config["host"]
|
14
|
+
})
|
15
|
+
p "ORM: #{Doozer::Configs.orm} initialized..."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "doozer/lib"
|
3
|
+
require "doozer/view_helpers"
|
4
|
+
|
5
|
+
module Doozer
|
6
|
+
|
7
|
+
# This class facilitates loading and rendering of partials.
|
8
|
+
#
|
9
|
+
# A partial is an ERB template which starts with an underscore. They behave the same as action view ERB template with the only difference of not having access to Controller instance variables.
|
10
|
+
#
|
11
|
+
# An example partial: app/views/controller_name/_partial.html.erb
|
12
|
+
#
|
13
|
+
# By default, the Doozer scaffold creates an app/views/global folder which can be used to place global partials like headers, footers, etc.
|
14
|
+
#
|
15
|
+
# Partials have access to Doozer::ViewHelpers.
|
16
|
+
#
|
17
|
+
# All view helpers in app/helpers are automatically included in the Partial class during app initialize.
|
18
|
+
#
|
19
|
+
# A partial can render another partial and so on and so on.
|
20
|
+
class Partial
|
21
|
+
attr_accessor :erb, :route
|
22
|
+
|
23
|
+
include ERB::Util
|
24
|
+
include Doozer::Util::Logger
|
25
|
+
include Doozer::ViewHelpers
|
26
|
+
|
27
|
+
APP_PATH = Dir.pwd
|
28
|
+
@@partials={}
|
29
|
+
|
30
|
+
def initialize(erb, locals, route)
|
31
|
+
@erb = erb
|
32
|
+
@route = route
|
33
|
+
if locals.kind_of? Hash
|
34
|
+
locals.each_pair {|key, value|
|
35
|
+
#p "#{key}:#{value}"
|
36
|
+
self.instance_variable_set("@#{key}".to_sym, value) # :@a, value
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def bind
|
42
|
+
@erb.result(binding)
|
43
|
+
end
|
44
|
+
|
45
|
+
# This class method lazily loads and caches the erb templates of the requested partials
|
46
|
+
def self.partial(file=nil, locals={}, route=route)
|
47
|
+
#p "Class method: Doozer::Partial#partial"
|
48
|
+
if file.index("/").nil?
|
49
|
+
name = "#{route.controller}/_#{file}"
|
50
|
+
else
|
51
|
+
name = "#{file.gsub(/\//,'/_')}"
|
52
|
+
end
|
53
|
+
load_partial(name) if @@partials[name].nil?
|
54
|
+
erb = @@partials[name]
|
55
|
+
if erb
|
56
|
+
partial = Doozer::Partial.new(erb, locals, route)
|
57
|
+
partial.bind()
|
58
|
+
else
|
59
|
+
p "no partial exists for #{file}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Renders and returns a partial template with the given file_name and local variables.
|
64
|
+
#
|
65
|
+
# * file - expects a string. By default, if you don't pass a controller, it's assumed the lookup location is the current route.controller path in the views folder.
|
66
|
+
# You must omit the underscore when passing the file_name.
|
67
|
+
# A partial is automatically assumed to be html format. It shouldn't matter if you display an html partial inside a view with a different format.
|
68
|
+
#
|
69
|
+
# * locals - All local key/values are instantiated as instance variables acessable from the partial template. The controller.request variable is appended to locals and is also accessable as an instance variable from the partial template.
|
70
|
+
def partial(file=nil, locals={})
|
71
|
+
locals[:request] = @request if not @request.nil?
|
72
|
+
Doozer::Partial.partial(file, locals, route=@route)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Load and cache partial ERB template with the given file_name.
|
76
|
+
def self.load_partial(name)
|
77
|
+
file = File.join(APP_PATH,"/app/views/#{name}.html.erb")
|
78
|
+
results = []
|
79
|
+
begin
|
80
|
+
File.new(file, "r").each { |line| results << line }
|
81
|
+
# TODO: throw error if doesn't exist
|
82
|
+
@@partials[name] = ERB.new(results.join(""))
|
83
|
+
rescue
|
84
|
+
p "sorry couldn't load partial #{name} (#{file})"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Class methods for clearing all cached partials. Mainly a dispatcher for the file watcher to pick up new changes without having to restart the appserver in development mode.
|
89
|
+
def self.clear_loaded_partials
|
90
|
+
@@partials = {}
|
91
|
+
end
|
92
|
+
|
93
|
+
# Class method for including a view helper.
|
94
|
+
def self.include_view_helper(helper)
|
95
|
+
m = Doozer::Lib.classify(helper)
|
96
|
+
include Object.const_get(m)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|