bang-bang 0.1.6
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/.gitignore +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +97 -0
- data/README.markdown +42 -0
- data/Rakefile +2 -0
- data/bang-bang.gemspec +38 -0
- data/lib/bang-bang/controller.rb +126 -0
- data/lib/bang-bang/env_methods.rb +13 -0
- data/lib/bang-bang/plugins/directory_first_sort.rb +14 -0
- data/lib/bang-bang/plugins.rb +29 -0
- data/lib/bang-bang/service.rb +176 -0
- data/lib/bang-bang/version.rb +3 -0
- data/lib/bang-bang/views.rb +81 -0
- data/lib/bang-bang.rb +130 -0
- data/spec/bang-bang/controller_spec.rb +36 -0
- data/spec/bang-bang/service_spec.rb +35 -0
- data/spec/bang-bang/views_spec.rb +46 -0
- data/spec/fixture-app/app.rb +30 -0
- data/spec/fixture-app/services/authentication/app/controllers/authentication.rb +6 -0
- data/spec/fixture-app/services/authentication/app/presenters/index.html.ms.rb +5 -0
- data/spec/fixture-app/services/authentication/app/templates/index.html.ms +4 -0
- data/spec/fixture-app/services/authentication/init.rb +1 -0
- data/spec/fixture-app/services/authentication/public/javascripts/foo.js +2 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/spec_helpers/example_group.rb +47 -0
- data/spec/spec_suite.rb +3 -0
- data/vendor/superhash/InstalledFiles +1 -0
- data/vendor/superhash/README +5 -0
- data/vendor/superhash/RELEASE-NOTES +9 -0
- data/vendor/superhash/config.save +12 -0
- data/vendor/superhash/examples/attributed-node.rb +83 -0
- data/vendor/superhash/examples/class-superhash.rb +26 -0
- data/vendor/superhash/examples/state-object.rb +95 -0
- data/vendor/superhash/install.rb +1015 -0
- data/vendor/superhash/lib/superhash.rb +454 -0
- data/vendor/superhash/test/test.rb +124 -0
- metadata +235 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.2-p290@bang-bang
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bang-bang (0.1.5)
|
5
|
+
activesupport (>= 2.0.0)
|
6
|
+
honkster-addressable (>= 2.2.3)
|
7
|
+
mustache
|
8
|
+
named-routes (>= 0.2.7)
|
9
|
+
sinatra (>= 1.2.0)
|
10
|
+
yajl-ruby (>= 0.8.1)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: http://rubygems.org/
|
14
|
+
specs:
|
15
|
+
activesupport (3.0.9)
|
16
|
+
addressable (2.2.4)
|
17
|
+
archive-tar-minitar (0.5.2)
|
18
|
+
capybara (0.4.0)
|
19
|
+
celerity (>= 0.7.9)
|
20
|
+
culerity (>= 0.2.4)
|
21
|
+
mime-types (>= 1.16)
|
22
|
+
nokogiri (>= 1.3.3)
|
23
|
+
rack (>= 1.0.0)
|
24
|
+
rack-test (>= 0.5.4)
|
25
|
+
selenium-webdriver (>= 0.0.27)
|
26
|
+
xpath (~> 0.1.2)
|
27
|
+
celerity (0.8.8)
|
28
|
+
childprocess (0.1.7)
|
29
|
+
ffi (~> 0.6.3)
|
30
|
+
columnize (0.3.2)
|
31
|
+
crack (0.1.8)
|
32
|
+
culerity (0.2.15)
|
33
|
+
diff-lcs (1.1.2)
|
34
|
+
ffi (0.6.3)
|
35
|
+
rake (>= 0.8.7)
|
36
|
+
honkster-addressable (2.2.3)
|
37
|
+
i18n (0.6.0)
|
38
|
+
json_pure (1.5.1)
|
39
|
+
linecache19 (0.5.11)
|
40
|
+
ruby_core_source (>= 0.1.4)
|
41
|
+
mime-types (1.16)
|
42
|
+
mustache (0.99.4)
|
43
|
+
named-routes (0.2.7)
|
44
|
+
activesupport (>= 2.0.0)
|
45
|
+
nokogiri (1.4.4)
|
46
|
+
rack (1.2.2)
|
47
|
+
rack-test (0.5.6)
|
48
|
+
rack (>= 1.0)
|
49
|
+
rake (0.8.7)
|
50
|
+
rr (1.0.2)
|
51
|
+
rspec (2.2.0)
|
52
|
+
rspec-core (~> 2.2)
|
53
|
+
rspec-expectations (~> 2.2)
|
54
|
+
rspec-mocks (~> 2.2)
|
55
|
+
rspec-core (2.5.1)
|
56
|
+
rspec-expectations (2.5.0)
|
57
|
+
diff-lcs (~> 1.1.2)
|
58
|
+
rspec-mocks (2.5.0)
|
59
|
+
ruby-debug-base19 (0.11.24)
|
60
|
+
columnize (>= 0.3.1)
|
61
|
+
linecache19 (>= 0.5.11)
|
62
|
+
ruby_core_source (>= 0.1.4)
|
63
|
+
ruby-debug19 (0.11.6)
|
64
|
+
columnize (>= 0.3.1)
|
65
|
+
linecache19 (>= 0.5.11)
|
66
|
+
ruby-debug-base19 (>= 0.11.19)
|
67
|
+
ruby_core_source (0.1.4)
|
68
|
+
archive-tar-minitar (>= 0.5.2)
|
69
|
+
rubyzip (0.9.4)
|
70
|
+
selenium-webdriver (0.1.3)
|
71
|
+
childprocess (~> 0.1.5)
|
72
|
+
ffi (~> 0.6.3)
|
73
|
+
json_pure
|
74
|
+
rubyzip
|
75
|
+
sinatra (1.2.6)
|
76
|
+
rack (~> 1.1)
|
77
|
+
tilt (>= 1.2.2, < 2.0)
|
78
|
+
tilt (1.3.2)
|
79
|
+
webmock (1.6.2)
|
80
|
+
addressable (>= 2.2.2)
|
81
|
+
crack (>= 0.1.7)
|
82
|
+
xpath (0.1.3)
|
83
|
+
nokogiri (~> 1.3)
|
84
|
+
yajl-ruby (0.8.2)
|
85
|
+
|
86
|
+
PLATFORMS
|
87
|
+
ruby
|
88
|
+
|
89
|
+
DEPENDENCIES
|
90
|
+
bang-bang!
|
91
|
+
capybara (>= 0.4.0)
|
92
|
+
i18n (>= 0.5.0)
|
93
|
+
rack-test (>= 0.5.6)
|
94
|
+
rr (>= 1.0.2)
|
95
|
+
rspec (>= 2.2.0)
|
96
|
+
ruby-debug19 (>= 0.11.6)
|
97
|
+
webmock (>= 1.6.2)
|
data/README.markdown
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# TrueWeb
|
2
|
+
|
3
|
+
TrueWeb is a lightweight Sinatra web VC stack. Currently, it doesn't have strong opinions, to allow flexibility to discover good idioms.
|
4
|
+
|
5
|
+
## Basic Layout
|
6
|
+
|
7
|
+
TrueWeb has a basic app structure, similar to Rails.
|
8
|
+
Right now, no conventions are "forced" on you. This is done to allow experimentation and keep things lightweight.
|
9
|
+
|
10
|
+
You pick the model library.
|
11
|
+
|
12
|
+
Right now there are no generators.
|
13
|
+
|
14
|
+
### TrueWeb::Controller
|
15
|
+
|
16
|
+
TrueWeb::Controller is a subclass of Sinatra::Base.
|
17
|
+
It's meant to provide an encapsulated unit of functionality within your app.
|
18
|
+
How you group your actions is up to you.
|
19
|
+
|
20
|
+
### NamedRoutes
|
21
|
+
|
22
|
+
TrueWeb uses the [named-routes](https://github.com/btakita/named-routes) library.
|
23
|
+
|
24
|
+
Here is a good pattern to follow:
|
25
|
+
|
26
|
+
module MyApp
|
27
|
+
Controller.define_routes do
|
28
|
+
def root; end
|
29
|
+
get path(:root, "/") do
|
30
|
+
"Hello World!"
|
31
|
+
end
|
32
|
+
|
33
|
+
def about_us; end
|
34
|
+
get path(:about_us, "/about-us") do
|
35
|
+
view("/about-us.html.ms")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Defining the route methods allows certain code editors & IDEs to locate the definition of action.
|
41
|
+
|
42
|
+
uris.about_us # /about-us
|
data/Rakefile
ADDED
data/bang-bang.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'bang-bang/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "bang-bang"
|
9
|
+
s.version = ::BangBang::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Brian Takita"]
|
12
|
+
s.email = ["btakita@truecar.com"]
|
13
|
+
s.homepage = "https://github.com/TrueCar/bang-bang"
|
14
|
+
s.summary = %q{A lightweight Sinatra web MVC stack}
|
15
|
+
s.description = %q{A lightweight Sinatra web MVC stack}
|
16
|
+
|
17
|
+
s.required_rubygems_version = ">= 1.3.6"
|
18
|
+
|
19
|
+
# Man files are required because they are ignored by git
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_dependency "activesupport", ">=2.0.0"
|
25
|
+
s.add_dependency "honkster-addressable", ">=2.2.3"
|
26
|
+
s.add_dependency "mustache"
|
27
|
+
s.add_dependency "named-routes", ">=0.2.7"
|
28
|
+
s.add_dependency "sinatra", ">=1.2.0"
|
29
|
+
s.add_dependency "yajl-ruby", ">=0.8.1"
|
30
|
+
|
31
|
+
s.add_development_dependency "capybara", ">=0.4.0"
|
32
|
+
s.add_development_dependency "i18n", ">=0.5.0"
|
33
|
+
s.add_development_dependency "rack-test", ">=0.5.6"
|
34
|
+
s.add_development_dependency "rr", ">=1.0.2"
|
35
|
+
s.add_development_dependency "rspec", ">=2.2.0"
|
36
|
+
s.add_development_dependency "ruby-debug19", ">=0.11.6"
|
37
|
+
s.add_development_dependency "webmock", ">=1.6.2"
|
38
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module BangBang
|
2
|
+
class Controller < Sinatra::Base
|
3
|
+
set :raise_errors, false
|
4
|
+
set :show_exceptions, false
|
5
|
+
|
6
|
+
class_inheritable_accessor :config
|
7
|
+
extend(Module.new do
|
8
|
+
def uris
|
9
|
+
config.uris
|
10
|
+
end
|
11
|
+
|
12
|
+
def views_class
|
13
|
+
config.views_class
|
14
|
+
end
|
15
|
+
|
16
|
+
def path(*args, &block)
|
17
|
+
uris.path(*args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def services
|
21
|
+
config.services
|
22
|
+
end
|
23
|
+
end)
|
24
|
+
|
25
|
+
TEMPLATE_TYPE_NAME = "Template"
|
26
|
+
|
27
|
+
set :logging, true
|
28
|
+
set :static, true
|
29
|
+
attr_reader :helper, :views
|
30
|
+
|
31
|
+
error(403) do
|
32
|
+
"<div>Sorry, the page you're trying to access is private.</div>"
|
33
|
+
end
|
34
|
+
|
35
|
+
error(404) do
|
36
|
+
"<div>Sorry, we could not find the page you were looking for.</div>"
|
37
|
+
end
|
38
|
+
|
39
|
+
error(500) do
|
40
|
+
env["rack.exception"] = env["sinatra.error"]
|
41
|
+
if env["rack.logger"]
|
42
|
+
env["rack.logger"].error "#{env["sinatra.error"].message}\n#{env["sinatra.error"].backtrace.join("\n\t")}"
|
43
|
+
end
|
44
|
+
"<div>Oops, an error occurred.</div>"
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
@views = self.class.views_class.new(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def services
|
52
|
+
self.class.services
|
53
|
+
end
|
54
|
+
|
55
|
+
def uris
|
56
|
+
self.class.uris
|
57
|
+
end
|
58
|
+
|
59
|
+
def view(path, *args)
|
60
|
+
views[path].render(*args)
|
61
|
+
end
|
62
|
+
|
63
|
+
def static!
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
module Controllers
|
68
|
+
module ClassMethods
|
69
|
+
def define_routes(&route_definition)
|
70
|
+
controller = Class.new(self)
|
71
|
+
controller.class_eval(&route_definition)
|
72
|
+
controllers << controller
|
73
|
+
end
|
74
|
+
|
75
|
+
def controllers
|
76
|
+
@controllers ||= []
|
77
|
+
end
|
78
|
+
|
79
|
+
def pagelet_access_resources(pagelet_json_path, paglet_asset_json_path, html_path=nil)
|
80
|
+
if html_path
|
81
|
+
get html_path do
|
82
|
+
send(html_path)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
get pagelet_json_path do
|
87
|
+
response['Content-Type'] = 'application/json'
|
88
|
+
send(paglet_asset_json_path).merge(
|
89
|
+
html_path ? {
|
90
|
+
:html => send(html_path)
|
91
|
+
} : {}
|
92
|
+
).to_json
|
93
|
+
end
|
94
|
+
|
95
|
+
get paglet_asset_json_path do
|
96
|
+
response['Content-Type'] = 'application/json'
|
97
|
+
send(paglet_asset_json_path).to_json
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.included(mod)
|
103
|
+
mod.extend(ClassMethods)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Overrode call! to speed up routing to subresources.
|
107
|
+
def call!(env)
|
108
|
+
self.class.controllers.each do |controller|
|
109
|
+
request = ::Sinatra::Request.new(env)
|
110
|
+
routes = controller.routes[request.request_method] || []
|
111
|
+
path = unescape(request.path_info)
|
112
|
+
routes.each do |pattern, keys, conditions, block|
|
113
|
+
if pattern.match(path)
|
114
|
+
subapp_instance = controller.allocate
|
115
|
+
subapp_instance.send(:initialize, nil)
|
116
|
+
response = subapp_instance.call(env)
|
117
|
+
return response if response[0] != 404
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
super
|
122
|
+
end
|
123
|
+
end
|
124
|
+
include Controllers
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BangBang
|
2
|
+
module Plugins
|
3
|
+
class Set
|
4
|
+
attr_reader :config
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_init(&block)
|
10
|
+
@on_init ||= []
|
11
|
+
if block
|
12
|
+
@on_init.push(block)
|
13
|
+
else
|
14
|
+
@on_init
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def init
|
19
|
+
self.on_init.each do |block|
|
20
|
+
block.call(config)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Dir["#{File.dirname(__FILE__)}/plugins/*.rb"].each do |file|
|
26
|
+
require file
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module BangBang
|
2
|
+
class Service
|
3
|
+
attr_reader :root_dir
|
4
|
+
attr_accessor :url_prefix
|
5
|
+
|
6
|
+
def initialize(dir)
|
7
|
+
@root_dir = dir
|
8
|
+
end
|
9
|
+
|
10
|
+
def init
|
11
|
+
init_controllers
|
12
|
+
autoload_models
|
13
|
+
append_load_paths
|
14
|
+
eval_init_rb
|
15
|
+
yield(self) if block_given?
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def append_load_paths
|
20
|
+
lib_dir = File.join(root_dir, "lib")
|
21
|
+
$LOAD_PATH << lib_dir if File.directory?(lib_dir)
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_presenter_file_path(url)
|
25
|
+
stripped_url_prefix = strip_url_prefix(url)
|
26
|
+
file_path = File.join(presenters_dir, "#{stripped_url_prefix}.rb")
|
27
|
+
File.file?(file_path) ? file_path : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_stylesheet_file_path(url)
|
31
|
+
stripped_url_prefix = strip_url_prefix(url)
|
32
|
+
file_path = File.join(app_dir, stripped_url_prefix.gsub(/\.css$/, ".sass"))
|
33
|
+
File.file?(file_path) ? file_path : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_static_file_path(url)
|
37
|
+
stripped_url_prefix = strip_url_prefix(url)
|
38
|
+
static_file_dirs.each do |dir|
|
39
|
+
file_path = File.join(dir, stripped_url_prefix)
|
40
|
+
return file_path if File.file?(file_path)
|
41
|
+
end
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_spec_urls(url)
|
46
|
+
specs_url_prefix = File.join(url_prefix.to_s, "specs")
|
47
|
+
stripped_url_prefix = strip_url_prefix(url, specs_url_prefix)
|
48
|
+
path = File.join(spec_javascripts_dir, stripped_url_prefix.to_s)
|
49
|
+
get_specs_urls_from_path(path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_specs_urls_from_path(path=spec_javascripts_dir)
|
53
|
+
(Dir["#{path}/**/*_spec.js"] + Dir["#{path}.js"]).flatten.compact.map do |file|
|
54
|
+
file.gsub(spec_javascripts_dir, File.join(url_prefix.to_s, "specs")).gsub("//", "/")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_spec_file_path(url)
|
59
|
+
specs_url_prefix = File.join(url_prefix.to_s, "specs")
|
60
|
+
stripped_url_prefix = strip_url_prefix(url, specs_url_prefix)
|
61
|
+
file_path = File.join(spec_javascripts_dir, stripped_url_prefix)
|
62
|
+
file_path if File.file?(file_path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def app_dir
|
66
|
+
File.join(root_dir, "app")
|
67
|
+
end
|
68
|
+
|
69
|
+
def presenters_dir
|
70
|
+
File.join(app_dir, "presenters")
|
71
|
+
end
|
72
|
+
|
73
|
+
def templates_dir
|
74
|
+
File.join(app_dir, "templates")
|
75
|
+
end
|
76
|
+
|
77
|
+
def stylesheets_dir
|
78
|
+
File.join(app_dir, "stylesheets")
|
79
|
+
end
|
80
|
+
|
81
|
+
def templates_hash
|
82
|
+
Dir["#{templates_dir}/**/*.*"].inject({}) do |memo, path|
|
83
|
+
memo[path.gsub(templates_dir, url_prefix.to_s)] = File.read(path)
|
84
|
+
memo
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def javascript_urls(params={})
|
89
|
+
return [] unless File.directory?(public_javascripts_dir)
|
90
|
+
glob = params[:glob] || "**/*.js"
|
91
|
+
cache_buster = params.has_key?(:cache_bust) ? params[:cache_bust] : true
|
92
|
+
Dir["#{public_javascripts_dir}/#{glob}"].sort_by(&BangBang::Plugins::DirectoryFirstSort.directory_first_sort).map do |file|
|
93
|
+
asset_url(file, file.gsub(public_javascripts_dir, "#{url_prefix}/javascripts"), cache_buster)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def stylesheet_urls(params = {})
|
98
|
+
return [] unless File.directory?(stylesheets_dir)
|
99
|
+
glob = params[:glob] || "**/[^_]*.css"
|
100
|
+
cache_buster = params.has_key?(:cache_bust) ? params[:cache_bust] : true
|
101
|
+
sass_glob = glob.gsub(/\.css$/, ".sass")
|
102
|
+
Dir["#{stylesheets_dir}/#{sass_glob}"].sort_by(&BangBang::Plugins::DirectoryFirstSort.directory_first_sort).map do |file|
|
103
|
+
asset_url(file, file.gsub(stylesheets_dir, "#{url_prefix}/stylesheets").gsub(/\.sass$/, ".css"), cache_buster)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def spec_javascripts_dir
|
108
|
+
File.join(root_dir, "spec/javascripts")
|
109
|
+
end
|
110
|
+
|
111
|
+
def init_controllers
|
112
|
+
controllers_dir = File.join(root_dir, "app/controllers")
|
113
|
+
if File.directory?(controllers_dir)
|
114
|
+
module_files = Dir["#{controllers_dir}/**/*.module.rb"]
|
115
|
+
module_files.each do |file|
|
116
|
+
require file
|
117
|
+
end
|
118
|
+
|
119
|
+
directory_first_sort = BangBang::Plugins::DirectoryFirstSort.directory_first_sort
|
120
|
+
(Dir["#{controllers_dir}/**/*.rb"] - module_files).sort_by(&directory_first_sort).each do |file|
|
121
|
+
require file
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def autoload_models
|
127
|
+
models_dir = File.join(root_dir, "app/models")
|
128
|
+
if File.directory?(models_dir)
|
129
|
+
directory_first_sort = BangBang::Plugins::DirectoryFirstSort.directory_first_sort
|
130
|
+
Dir["#{models_dir}/**/*.rb"].sort_by(&directory_first_sort).each do |file|
|
131
|
+
const_name_parts = file.
|
132
|
+
gsub(models_dir, "").
|
133
|
+
gsub("-", "_").
|
134
|
+
gsub(/\.rb/, "").
|
135
|
+
camelize.
|
136
|
+
split("::").
|
137
|
+
select {|part| part.present?}
|
138
|
+
parent_const = const_name_parts[0..-2].join("::").constantize
|
139
|
+
parent_const.autoload const_name_parts[-1].to_sym, file
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def public_dir
|
145
|
+
File.join(root_dir, "public")
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
def asset_url(file, url_path, cache_buster)
|
150
|
+
if cache_buster
|
151
|
+
"#{url_path}?_cb=#{File.mtime(file).to_i}"
|
152
|
+
else
|
153
|
+
url_path
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def static_file_dirs
|
158
|
+
[public_dir, templates_dir]
|
159
|
+
end
|
160
|
+
|
161
|
+
def public_javascripts_dir
|
162
|
+
File.join(public_dir, "javascripts")
|
163
|
+
end
|
164
|
+
|
165
|
+
def strip_url_prefix(url_path, prefix=url_prefix)
|
166
|
+
url_path.gsub(Regexp.new("^#{prefix}"), "")
|
167
|
+
end
|
168
|
+
|
169
|
+
def eval_init_rb
|
170
|
+
init_rb_path = "#{root_dir}/init.rb"
|
171
|
+
if File.exists?(init_rb_path)
|
172
|
+
instance_eval(File.read(init_rb_path), init_rb_path, 1)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module BangBang
|
2
|
+
class Views
|
3
|
+
delegate :cookies, :current_user, :logged_in_user, :request, :response, :uris, :env, :params, :services, :to => :app_instance
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def mustache(template_path, &definition)
|
7
|
+
define_method_via_include(template_path, &definition)
|
8
|
+
define_method_via_include(template_path) do |*args|
|
9
|
+
Mustache.render(template_content(template_path), self.class.metadata(template_path).merge(super(*args)))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def text(path, &definition)
|
14
|
+
define_method_via_include(path, &definition)
|
15
|
+
end
|
16
|
+
|
17
|
+
def metadata(path)
|
18
|
+
{
|
19
|
+
'data-template' => path,
|
20
|
+
'data-type' => "Template"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def define_method_via_include(method_name, &definition)
|
25
|
+
include(Module.new do
|
26
|
+
define_method(method_name, &definition)
|
27
|
+
end)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :app_instance
|
32
|
+
|
33
|
+
def initialize(app_instance)
|
34
|
+
@app_instance = app_instance
|
35
|
+
end
|
36
|
+
|
37
|
+
def app
|
38
|
+
app_instance.class
|
39
|
+
end
|
40
|
+
|
41
|
+
def config
|
42
|
+
app_instance.config
|
43
|
+
end
|
44
|
+
|
45
|
+
def [](path)
|
46
|
+
unless respond_to?(path)
|
47
|
+
config.services.find do |service|
|
48
|
+
presenter_path = service.get_presenter_file_path(path)
|
49
|
+
if presenter_path
|
50
|
+
class_eval File.read(presenter_path), presenter_path, 1
|
51
|
+
end
|
52
|
+
end || begin
|
53
|
+
self.class.mustache(path) {|*_| {}}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
o = lambda do |*args|
|
58
|
+
send(path, *args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def o.render(*args)
|
62
|
+
self.call(*args)
|
63
|
+
end
|
64
|
+
o
|
65
|
+
end
|
66
|
+
|
67
|
+
def template_content(relative_path)
|
68
|
+
File.read(full_path(relative_path))
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
def full_path(relative_path)
|
74
|
+
services.each do |service|
|
75
|
+
path = service.get_static_file_path(relative_path)
|
76
|
+
return path if path
|
77
|
+
end
|
78
|
+
raise ArgumentError, "Path #{relative_path.inspect} does not exist in any of the services."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|