true-web 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module TrueWeb
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,85 @@
1
+ module TrueWeb
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
+ }.only(*metadata_keys)
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
+
30
+ def metadata_keys
31
+ ['data-template', 'data-type']
32
+ end
33
+ end
34
+
35
+ attr_reader :app_instance
36
+
37
+ def initialize(app_instance)
38
+ @app_instance = app_instance
39
+ end
40
+
41
+ def app
42
+ app_instance.class
43
+ end
44
+
45
+ def config
46
+ app_instance.config
47
+ end
48
+
49
+ def [](path)
50
+ unless respond_to?(path)
51
+ config.services.find do |service|
52
+ presenter_path = service.get_presenter_file_path(path)
53
+ if presenter_path
54
+ class_eval File.read(presenter_path), presenter_path, 1
55
+ end
56
+ end || begin
57
+ self.class.mustache(path) {|*_| {}}
58
+ end
59
+ end
60
+
61
+ o = lambda do |*args|
62
+ send(path, *args)
63
+ end
64
+
65
+ def o.render(*args)
66
+ self.call(*args)
67
+ end
68
+ o
69
+ end
70
+
71
+ def template_content(relative_path)
72
+ File.read(full_path(relative_path))
73
+ end
74
+
75
+ protected
76
+
77
+ def full_path(relative_path)
78
+ services.each do |service|
79
+ path = service.get_static_file_path(relative_path)
80
+ return path if path
81
+ end
82
+ raise ArgumentError, "Path #{relative_path.inspect} does not exist in any of the services."
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,26 @@
1
+ module FixtureApp
2
+ include ::TrueWeb
3
+
4
+ def self.app
5
+ @app ||= Rack::Builder.new do
6
+ run ::FixtureApp::Controller
7
+ end.to_app
8
+ end
9
+
10
+ class Controller < ::TrueWeb::Controller
11
+ end
12
+
13
+ class Views < ::TrueWeb::Views
14
+ end
15
+
16
+ class Routes < NamedRoutes::Routes
17
+ end
18
+ end
19
+
20
+ FixtureApp.init(
21
+ :controller => FixtureApp::Controller,
22
+ :application_name => "fixture-app",
23
+ :root_dir => File.dirname(__FILE__),
24
+ :named_routes => FixtureApp::Routes,
25
+ :views_class => FixtureApp::Views
26
+ )
@@ -0,0 +1 @@
1
+ <div class="authentication-index"></div>
@@ -0,0 +1 @@
1
+ self.url_prefix = "/authentication"
@@ -0,0 +1,2 @@
1
+ function Foo() {
2
+ }
@@ -0,0 +1,50 @@
1
+ require "rubygems"
2
+ dir = File.dirname(__FILE__)
3
+
4
+ $LOAD_PATH.unshift(File.expand_path("#{dir}/../lib"))
5
+
6
+ require "rack/test"
7
+
8
+ require "true-web"
9
+ require "#{dir}/fixture-app/app"
10
+
11
+ gem "nokogiri"
12
+ gem "rack-test", "0.5.6"
13
+ gem "capybara", "0.4.0"
14
+ gem "honkster-addressable", "2.2.3"
15
+
16
+ require "rack/session/abstract/id"
17
+ require "rack/test"
18
+ require "capybara"
19
+ require "capybara/dsl"
20
+ require "nokogiri"
21
+ require "addressable/uri"
22
+
23
+ ARGV.push("-b")
24
+ unless ARGV.include?("--format") || ARGV.include?("-f")
25
+ ARGV.push("--format", "nested")
26
+ end
27
+
28
+ require 'rspec'
29
+ require 'rspec/autorun'
30
+ require 'rr'
31
+ require 'webmock/rspec'
32
+
33
+ ENV["RACK_ENV"] = "test"
34
+
35
+ Dir["#{File.dirname(__FILE__)}/spec_helpers/**/*.rb"].each do |file|
36
+ require file
37
+ end
38
+
39
+ RSpec.configure do |configuration|
40
+ configuration.mock_with :rr
41
+ configuration.filter_run :focus => true
42
+ configuration.run_all_when_everything_filtered = true
43
+ configuration.before do
44
+ Capybara.reset!
45
+
46
+ FixtureApp.views_class = FixtureApp::Views
47
+ end
48
+ end
49
+
50
+ Capybara.app = FixtureApp.app
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/**/*_spec.rb"].each do |file|
2
+ require file
3
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module TrueWeb
4
+ describe Service do
5
+ describe "#get_static_file_path" do
6
+ context "when the service has a file matching the given url" do
7
+ it "returns the file path of the static file base on the Service's prefix + file path" do
8
+ authentication_path = "#{FixtureApp.root_dir}/services/authentication"
9
+ service = Service.new(authentication_path).init
10
+ service.url_prefix.should == "/authentication"
11
+ service.get_static_file_path("/authentication/javascripts/foo.js").should ==
12
+ File.join(authentication_path, "/public/javascripts/foo.js")
13
+ end
14
+ end
15
+
16
+ context "when the service does not have a file matching the given url" do
17
+ it "returns nil" do
18
+ authentication_path = "#{FixtureApp.root_dir}/services/authentication"
19
+ service = Service.new(authentication_path).init
20
+ service.get_static_file_path("i-dont-exist").should be_nil
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#templates_hash" do
26
+ it "returns a hash of all of the template files" do
27
+ authentication_path = "#{FixtureApp.root_dir}/services/authentication"
28
+ service = Service.new(authentication_path).init
29
+
30
+ hash = service.templates_hash
31
+ hash["/authentication/index.html.ms"].should == File.read(File.join(service.templates_dir, "index.html.ms"))
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module TrueWeb
4
+ describe Views do
5
+ describe "#[]" do
6
+ it "returns an object with a render method, which invokes the given method name" do
7
+ view = TrueWeb::Views.new(Object.new)
8
+ mock(view, "true_car_makes")
9
+
10
+ view["true_car_makes"].render
11
+ end
12
+
13
+ describe "lazily created method" do
14
+ context "when the presenter file exists" do
15
+ it "evals the presenter file (which is responsible for adding the method)" do
16
+ pending "Testing"
17
+ end
18
+ end
19
+
20
+ context "when the presenter file does not exist" do
21
+ it "lazily creates a method that render the mustache template for the given path" do
22
+ app_instance = Object.new
23
+ app_instance.class.send(:define_method, :config) do
24
+ FixtureApp
25
+ end
26
+ views = Class.new(TrueWeb::Views).new(app_instance)
27
+
28
+ views.respond_to?("/user/pagelets/i-dont-exist").should be_false
29
+ views["/user/pagelets/i-dont-exist"]
30
+ views.respond_to?("/user/pagelets/i-dont-exist").should be_true
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
data/true-web.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'true-web/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "true-web"
9
+ s.version = ::TrueWeb::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/true-web"
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", ">=3.0.0"
25
+ s.add_dependency "honkster-addressable", ">=2.2.3"
26
+ s.add_dependency "i18n", ">=0.5.0"
27
+ s.add_dependency "mustache", ">=0.99.2"
28
+ s.add_dependency "named-routes", ">=0.2.5"
29
+ s.add_dependency "sinatra", ">=1.2.0"
30
+ s.add_dependency "yajl-ruby", ">=0.8.1"
31
+
32
+ s.add_development_dependency "capybara", ">=0.4.0"
33
+ s.add_development_dependency "nokogiri", ">=1.4.4"
34
+ s.add_development_dependency "rack-test", ">=0.5.6"
35
+ s.add_development_dependency "rr", ">=1.0.2"
36
+ s.add_development_dependency "rspec", ">=2.2.0"
37
+ s.add_development_dependency "ruby-debug19", ">=0.11.6"
38
+ s.add_development_dependency "webmock", ">=1.6.2"
39
+ end
@@ -0,0 +1 @@
1
+ /home/honk/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/site_ruby/1.9.1//superhash.rb
@@ -0,0 +1,5 @@
1
+ To install:
2
+
3
+ ruby install.rb config
4
+ ruby install.rb setup
5
+ ruby install.rb install
@@ -0,0 +1,9 @@
1
+ superhash 0.3
2
+ - Fixed broken #index.
3
+ - Updated for ruby-1.8 and ruby-1.9.
4
+
5
+ superhash 0.2
6
+ - Updated for ruby-1.7.3.
7
+
8
+ superhash 0.1
9
+ - First public release.
@@ -0,0 +1,12 @@
1
+ prefix=/home/honk/.rvm/rubies/ruby-1.9.2-p0
2
+ std-ruby=$prefix/lib/ruby/1.9.1
3
+ site-ruby-common=$prefix/lib/ruby/site_ruby
4
+ site-ruby=$prefix/lib/ruby/site_ruby/1.9.1
5
+ bin-dir=$prefix/bin
6
+ rb-dir=$site-ruby
7
+ so-dir=$prefix/lib/ruby/site_ruby/1.9.1/x86_64-linux
8
+ data-dir=$prefix/share
9
+ ruby-path=/home/honk/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
10
+ ruby-prog=/home/honk/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
11
+ make-prog=make
12
+ without-ext=no
@@ -0,0 +1,83 @@
1
+ require 'superhash'
2
+
3
+ # Example of using SuperHashes inside regular objects (not classes).
4
+ # This example was distilled from the SuperML project.
5
+
6
+ class AttributedNode
7
+
8
+ attr_reader :attributes, :parents, :children
9
+
10
+ # creates a node and gives it a first parent
11
+ def initialize(parent = nil)
12
+ @attributes = SuperHash.new(parent && parent.attributes)
13
+ @parents = parent ? [parent] : []
14
+ @children = []
15
+ end
16
+
17
+ # adds more parents, which will also contribute attributes
18
+ def add_parent(parent)
19
+ unless @parents.include? parent
20
+ @parents << parent
21
+ @attributes.parents << parent.attributes
22
+ end
23
+ self
24
+ end
25
+ protected :add_parent
26
+
27
+ def add_child(child)
28
+ @children << child
29
+ child.add_parent(self)
30
+ self
31
+ end
32
+
33
+ end
34
+
35
+ # This might be the description of a window using some (imaginary)
36
+ # GUI construction library.
37
+
38
+ root = AttributedNode.new
39
+ root.attributes[:type] = :top_window
40
+ root.attributes[:name] = "Feature request window"
41
+ root.attributes[:bg_color] = "gray"
42
+ root.attributes[:font_face] = "Courier"
43
+ root.attributes[:font_size] = 10
44
+
45
+ user_field = AttributedNode.new
46
+ root.add_child(user_field)
47
+ user_field.attributes[:type] = :text_box
48
+ user_field.attributes[:name] = "Username box"
49
+ user_field.attributes[:label] = "Name:"
50
+
51
+ feature_field = AttributedNode.new
52
+ root.add_child(feature_field)
53
+ feature_field.attributes[:type] = :text_box
54
+ feature_field.attributes[:name] = "Feature description box"
55
+ feature_field.attributes[:bg_color] = "white"
56
+ feature_field.attributes[:label] = "Please enter your request below:"
57
+ feature_field.attributes[:font_face] = "Times"
58
+ feature_field.attributes[:font_size] = 12
59
+
60
+
61
+ # So then we have:
62
+
63
+ p user_field.attributes[:bg_color] # ==> "gray"
64
+ p feature_field.attributes[:bg_color] # ==> "white"
65
+
66
+ p user_field.attributes[:font_size] # ==> 10
67
+ p feature_field.attributes[:font_size] # ==> 12
68
+
69
+
70
+ # You could even manage another set of attributes of the same objects using
71
+ # multiple inheritance, such as attributes pertaining to form entry content:
72
+
73
+ form_entry = AttributedNode.new
74
+ form_entry.attributes[:default_contents] = "enter text here"
75
+ form_entry.attributes[:reject_condition] = /[^\w,.;:?!]/
76
+
77
+ form_entry.add_child(user_field)
78
+ user_field.attributes[:default_contents] = "fred"
79
+
80
+ form_entry.add_child(feature_field)
81
+ feature_field.attributes[:reject_condition] = /more like Microsoft/
82
+
83
+ p feature_field.attributes[:default_contents] # ==> "enter text here"
@@ -0,0 +1,26 @@
1
+ require 'superhash'
2
+
3
+ class A
4
+ class_superhash :options
5
+
6
+ options[:foo] = "A foo"
7
+ options[:bar] = "A bar"
8
+
9
+ def options; self.class.options; end
10
+ end
11
+
12
+ class B < A
13
+ options[:foo] = "B foo"
14
+ end
15
+
16
+ p A.options
17
+ p B.options.to_hash
18
+ p B.new.options.to_hash
19
+
20
+ __END__
21
+
22
+ output:
23
+
24
+ {:foo=>"A foo", :bar=>"A bar"}
25
+ {:foo=>"B foo", :bar=>"A bar"}
26
+ {:foo=>"B foo", :bar=>"A bar"}