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.
@@ -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"}