true-web 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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .idea
2
+ *.gem
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2-p180@true-web
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ if respond_to? :source
2
+ source :gemcutter
3
+ source "http://gems.github.com"
4
+ end
5
+
6
+ gemspec :name => "true-web"
data/Gemfile.lock ADDED
@@ -0,0 +1,99 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ true-web (0.1.0)
5
+ activesupport (>= 3.0.0)
6
+ honkster-addressable (>= 2.2.3)
7
+ i18n (>= 0.5.0)
8
+ mustache (>= 0.99.2)
9
+ named-routes (>= 0.2.5)
10
+ sinatra (>= 1.2.0)
11
+ yajl-ruby (>= 0.8.1)
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ remote: http://gems.github.com/
16
+ specs:
17
+ activesupport (3.0.9)
18
+ addressable (2.2.4)
19
+ archive-tar-minitar (0.5.2)
20
+ capybara (0.4.0)
21
+ celerity (>= 0.7.9)
22
+ culerity (>= 0.2.4)
23
+ mime-types (>= 1.16)
24
+ nokogiri (>= 1.3.3)
25
+ rack (>= 1.0.0)
26
+ rack-test (>= 0.5.4)
27
+ selenium-webdriver (>= 0.0.27)
28
+ xpath (~> 0.1.2)
29
+ celerity (0.8.8)
30
+ childprocess (0.1.7)
31
+ ffi (~> 0.6.3)
32
+ columnize (0.3.2)
33
+ crack (0.1.8)
34
+ culerity (0.2.15)
35
+ diff-lcs (1.1.2)
36
+ ffi (0.6.3)
37
+ rake (>= 0.8.7)
38
+ honkster-addressable (2.2.3)
39
+ i18n (0.6.0)
40
+ json_pure (1.5.1)
41
+ linecache19 (0.5.11)
42
+ ruby_core_source (>= 0.1.4)
43
+ mime-types (1.16)
44
+ mustache (0.99.4)
45
+ named-routes (0.2.6)
46
+ activesupport (>= 3.0.0)
47
+ nokogiri (1.4.4)
48
+ rack (1.2.2)
49
+ rack-test (0.5.6)
50
+ rack (>= 1.0)
51
+ rake (0.8.7)
52
+ rr (1.0.2)
53
+ rspec (2.2.0)
54
+ rspec-core (~> 2.2)
55
+ rspec-expectations (~> 2.2)
56
+ rspec-mocks (~> 2.2)
57
+ rspec-core (2.5.1)
58
+ rspec-expectations (2.5.0)
59
+ diff-lcs (~> 1.1.2)
60
+ rspec-mocks (2.5.0)
61
+ ruby-debug-base19 (0.11.24)
62
+ columnize (>= 0.3.1)
63
+ linecache19 (>= 0.5.11)
64
+ ruby_core_source (>= 0.1.4)
65
+ ruby-debug19 (0.11.6)
66
+ columnize (>= 0.3.1)
67
+ linecache19 (>= 0.5.11)
68
+ ruby-debug-base19 (>= 0.11.19)
69
+ ruby_core_source (0.1.4)
70
+ archive-tar-minitar (>= 0.5.2)
71
+ rubyzip (0.9.4)
72
+ selenium-webdriver (0.1.3)
73
+ childprocess (~> 0.1.5)
74
+ ffi (~> 0.6.3)
75
+ json_pure
76
+ rubyzip
77
+ sinatra (1.2.6)
78
+ rack (~> 1.1)
79
+ tilt (>= 1.2.2, < 2.0)
80
+ tilt (1.3.2)
81
+ webmock (1.6.2)
82
+ addressable (>= 2.2.2)
83
+ crack (>= 0.1.7)
84
+ xpath (0.1.3)
85
+ nokogiri (~> 1.3)
86
+ yajl-ruby (0.8.2)
87
+
88
+ PLATFORMS
89
+ ruby
90
+
91
+ DEPENDENCIES
92
+ capybara (>= 0.4.0)
93
+ nokogiri (>= 1.4.4)
94
+ rack-test (>= 0.5.6)
95
+ rr (>= 1.0.2)
96
+ rspec (>= 2.2.0)
97
+ ruby-debug19 (>= 0.11.6)
98
+ true-web!
99
+ webmock (>= 1.6.2)
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/lib/true-web.rb ADDED
@@ -0,0 +1,131 @@
1
+ dir = File.dirname(__FILE__)
2
+ Dir[File.expand_path("#{dir}/../vendor/*/lib")].each do |path|
3
+ $LOAD_PATH.unshift(path)
4
+ end
5
+ require 'nokogiri'
6
+ require 'sinatra/base'
7
+ require 'mustache'
8
+ require 'yajl'
9
+ require 'active_support/all'
10
+ require 'addressable/uri'
11
+ require "named-routes"
12
+ require "superhash"
13
+ require "#{dir}/true-web/version"
14
+ require "#{dir}/true-web/env_methods"
15
+
16
+ module TrueWeb
17
+ def self.included(mod)
18
+ mod.extend(ClassMethods)
19
+ end
20
+
21
+ module ClassMethods
22
+ attr_accessor :controller, :application_name, :named_routes, :stderr_dir, :stdout_dir, :root_dir, :views_class
23
+ alias_method :uris, :named_routes
24
+ delegate :define_routes, :to => :controller
25
+
26
+ include ::TrueWeb::EnvMethods
27
+
28
+ def init(params={})
29
+ self.controller = params[:controller] || raise(ArgumentError, "You must provide an :controller param")
30
+ self.application_name = params[:application_name] || raise(ArgumentError, "You must provide an :application_name param")
31
+ self.root_dir = params[:root_dir] || raise(ArgumentError, "You must provide a :root_dir param")
32
+ self.named_routes = params[:named_routes] || raise(ArgumentError, "You must provide a :named_routes param")
33
+ self.views_class = params[:views_class] || raise(ArgumentError, "You must provide a :views_class param")
34
+ self.controller.config = self
35
+
36
+ plugins.init
37
+ end
38
+
39
+ def app
40
+ @app ||= Rack::Builder.new do
41
+ run controller
42
+ end.to_app
43
+ end
44
+
45
+ def register_service(path, &block)
46
+ unless service_dirs.include?(path)
47
+ service = Service.new(path)
48
+ services << service
49
+ service.init(&block)
50
+ end
51
+ end
52
+
53
+ def service_dirs
54
+ services.map do |service|
55
+ service.root_dir
56
+ end
57
+ end
58
+
59
+ def services
60
+ @services ||= []
61
+ end
62
+
63
+ def services_by_url_prefix
64
+ services.group_by do |service|
65
+ service.url_prefix
66
+ end
67
+ end
68
+
69
+ def services_by_root_dir
70
+ services.inject({}) do |memo, service|
71
+ memo[service.root_dir] = service
72
+ memo
73
+ end
74
+ end
75
+
76
+ def stderr_logger
77
+ @stderr_logger ||= Logger.new(stderr_dir)
78
+ end
79
+
80
+ def stdout_logger
81
+ @stdout_logger ||= Logger.new(stdout_dir)
82
+ end
83
+
84
+ def plugins
85
+ @plugins ||= ::TrueWeb::Plugins::Set.new(self)
86
+ end
87
+
88
+ def lib_dir
89
+ File.join(root_dir, "lib")
90
+ end
91
+
92
+ def stylesheets_dirs
93
+ service_subdirectory_dirs "app/stylesheets"
94
+ end
95
+
96
+ def vendor_dir
97
+ File.join(root_dir, "vendor")
98
+ end
99
+
100
+ def services_dir
101
+ File.join(root_dir, "services")
102
+ end
103
+
104
+ def service_subdirectory_dirs(relative_directory)
105
+ service_dirs.flatten.map do |service_path|
106
+ full_path = File.join(service_path, relative_directory)
107
+ full_path if File.directory?(full_path)
108
+ end.compact
109
+ end
110
+
111
+ def stderr_dir
112
+ "#{root_dir}/log/#{application_name}.#{rack_env}.stderr.log"
113
+ end
114
+
115
+ def stdout_dir
116
+ "#{root_dir}/log/#{application_name}.#{rack_env}.stdout.log"
117
+ end
118
+
119
+ def remove_generated_files
120
+ Dir["#{root_dir}/**/public/**/*.generated"].each do |generated_path|
121
+ FileUtils.rm_f(File.join(File.dirname(generated_path), File.basename(generated_path, ".generated")))
122
+ FileUtils.rm_f(generated_path)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ require "#{dir}/true-web/controller"
129
+ require "#{dir}/true-web/service"
130
+ require "#{dir}/true-web/views"
131
+ require "#{dir}/true-web/plugins"
@@ -0,0 +1,123 @@
1
+ module TrueWeb
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
+ "<div>Oops, an error occurred.</div>"
42
+ end
43
+
44
+ before do
45
+ @views = self.class.views_class.new(self)
46
+ end
47
+
48
+ def services
49
+ self.class.services
50
+ end
51
+
52
+ def uris
53
+ self.class.uris
54
+ end
55
+
56
+ def view(path, *args)
57
+ views[path].render(*args)
58
+ end
59
+
60
+ def static!
61
+ nil
62
+ end
63
+
64
+ module Controllers
65
+ module ClassMethods
66
+ def define_routes(&route_definition)
67
+ controller = Class.new(self)
68
+ controller.class_eval(&route_definition)
69
+ controllers << controller
70
+ end
71
+
72
+ def controllers
73
+ @controllers ||= []
74
+ end
75
+
76
+ def pagelet_access_resources(pagelet_json_path, paglet_asset_json_path, html_path=nil)
77
+ if html_path
78
+ get html_path do
79
+ send(html_path)
80
+ end
81
+ end
82
+
83
+ get pagelet_json_path do
84
+ response['Content-Type'] = 'application/json'
85
+ send(paglet_asset_json_path).merge(
86
+ html_path ? {
87
+ :html => send(html_path)
88
+ } : {}
89
+ ).to_json
90
+ end
91
+
92
+ get paglet_asset_json_path do
93
+ response['Content-Type'] = 'application/json'
94
+ send(paglet_asset_json_path).to_json
95
+ end
96
+ end
97
+ end
98
+
99
+ def self.included(mod)
100
+ mod.extend(ClassMethods)
101
+ end
102
+
103
+ # Overrode call! to speed up routing to subresources.
104
+ def call!(env)
105
+ self.class.controllers.each do |controller|
106
+ request = ::Sinatra::Request.new(env)
107
+ routes = controller.routes[request.request_method] || []
108
+ path = unescape(request.path_info)
109
+ routes.each do |pattern, keys, conditions, block|
110
+ if pattern.match(path)
111
+ subapp_instance = controller.allocate
112
+ subapp_instance.send(:initialize, nil)
113
+ response = subapp_instance.call(env)
114
+ return response if response[0] != 404
115
+ end
116
+ end
117
+ end
118
+ super
119
+ end
120
+ end
121
+ include Controllers
122
+ end
123
+ end
@@ -0,0 +1,13 @@
1
+ module TrueWeb
2
+ module EnvMethods
3
+ def development?
4
+ rack_env == "development"
5
+ end
6
+
7
+ def rack_env
8
+ ENV["RACK_ENV"]
9
+ end
10
+
11
+ extend self
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module TrueWeb
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,14 @@
1
+ module TrueWeb
2
+ module Plugins
3
+ module DirectoryFirstSort
4
+ def directory_first_sort
5
+ lambda do |path|
6
+ dir = File.dirname(path)
7
+ [dir.length, dir, File.basename(path)]
8
+ end
9
+ end
10
+
11
+ extend self
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,176 @@
1
+ module TrueWeb
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(&TrueWeb::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(&TrueWeb::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 = TrueWeb::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 = TrueWeb::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