happy 0.1.0.pre16 → 0.1.0.pre19

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/README.md CHANGED
@@ -25,7 +25,7 @@ run Happy
25
25
 
26
26
  How about something a little bit closer to reality?
27
27
 
28
- ``` ruby
28
+ ```ruby
29
29
  # config.ru
30
30
  require 'happy'
31
31
 
@@ -112,7 +112,6 @@ Happy is being extracted from a web application that I've been working on. I'm t
112
112
 
113
113
  FWIW, here's a list of important things still missing right now:
114
114
 
115
- * Nicer error pages for 404s, 401s etc.
116
115
  * Better logging.
117
116
  * Improved view engine compatibility.
118
117
 
data/happy.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_dependency 'activesupport', '~> 3.1'
19
19
  gem.add_dependency 'rack', '~> 1.4'
20
- gem.add_dependency 'happy-helpers', '~> 0.1.0.pre9'
20
+ gem.add_dependency 'happy-helpers', '~> 0.1.0.pre10'
21
21
  gem.add_dependency 'allowance', '>= 0.1.1'
22
22
 
23
23
  gem.add_dependency 'happy-cli', '>= 0.1.0.pre1'
@@ -15,7 +15,8 @@ module Happy
15
15
  end
16
16
 
17
17
  def render_template(name, variables = {}, &blk)
18
- HappyHelpers::Templates.render(name, self, variables, &blk)
18
+ path = @controller ? @controller.config[:views] : './views'
19
+ HappyHelpers::Templates.render(File.join(path, name), self, variables, &blk)
19
20
  end
20
21
 
21
22
  def render_resource(resource, options = {})
data/lib/happy/context.rb CHANGED
@@ -2,40 +2,87 @@ require 'happy/request'
2
2
  require 'happy/context/helpers'
3
3
 
4
4
  module Happy
5
+ # Represents the current request and its respective application state.
6
+ # Not only does this class wrap around both the incoming {#request} and the
7
+ # generated {#response}, but it is also used as the scope for all templates
8
+ # rendered through {#render_template}.
9
+ #
10
+ # (In case you're wondering, a particular request's instance of #{Context} is
11
+ # created from the Rack environment by #{Controller#context} when first accessed.)
12
+ #
13
+ # == View Helpers
14
+ #
15
+ # If you're coming from other web frameworks and looking for the right place
16
+ # to add "view helpers", this is it, since all templates being rendered use
17
+ # the request's instance of {Context} as their scope.
18
+ #
19
+ # The most convenient way of extending this class is through #{Happy.context}.
20
+ #
21
+ # Happy.context do
22
+ # def some_helper
23
+ # "I'm a view helper!"
24
+ # end
25
+ # end
26
+ #
27
+ # In addition to view helpers, the context is the place to add methods
28
+ # dealing with the current request scope, eg. methods like 'current_user'.
29
+ #
5
30
  class Context
6
31
  include Helpers
7
32
 
8
- attr_reader :request, :previous_path, :remaining_path
9
- attr_accessor :layout, :controller, :response
10
- delegate :params, :session, :to => :request
33
+ # Instance of {Happy::Request} representing the current HTTP request.
34
+ attr_reader :request
35
+
36
+ # The Rack::Response instance being used to compose the response.
37
+ attr_accessor :response
38
+
39
+ # The current layout template to be used when rendering the response.
40
+ attr_accessor :layout
41
+
42
+ # Array containing path parts that are yet to be handled.
43
+ attr_reader :remaining_path
44
+
45
+ # Array of path parts that have been handled so far.
46
+ attr_reader :previous_path
47
+
48
+ delegate :params, :session, :to => :request
49
+
50
+ # Initializes a new {Context} instance from a Rack environment hash.
51
+ #
52
+ # @param [Hash] env Rack environment hash
53
+ #
54
+ def initialize(env)
55
+ @request = Happy::Request.new(env)
56
+ @response = Rack::Response.new
11
57
 
12
- def initialize(request, response)
13
- @request = request
14
- @response = response
15
58
  @remaining_path = @request.path.split('/').reject {|s| s.blank? }
16
- @previous_path = []
17
- @layout = nil
18
- @controller = nil
59
+ @previous_path = []
60
+ @layout = nil
61
+ @controller = nil
19
62
  end
20
63
 
64
+ # @note
65
+ # This method is mostly used internally by Happy. You will not need
66
+ # to call it from your own controllers or applications.
67
+ #
68
+ # Execute the provided block, but register the provided {Controller}
69
+ # instance as the controller currently handling the request. Call this
70
+ # whenever you're passing control from one controller to another.
71
+ #
72
+ # @param [Controller] new_controller The {Controller} instance to set as the current controller
73
+ # @return Results of provided block.
74
+ #
21
75
  def with_controller(new_controller)
22
76
  # remember previous controller
23
- old_controller = self.controller
24
- self.controller = new_controller
77
+ old_controller = @controller
78
+ @controller = new_controller
25
79
 
26
80
  # execute block
27
- yield
81
+ yield if block_given?
28
82
  ensure
29
83
  # switch back to previous controller
30
- self.controller = old_controller
84
+ @controller = old_controller
31
85
  end
32
86
 
33
- private
34
-
35
- class << self
36
- def from_env(env)
37
- new(Happy::Request.new(env), Rack::Response.new)
38
- end
39
- end
40
87
  end
41
88
  end
@@ -2,51 +2,47 @@ module Happy
2
2
  class Controller
3
3
  module Actions
4
4
  def serve!(data, options = {})
5
- # Don't serve if there are still bits of path remaining.
6
- return unless remaining_path.empty?
5
+ only_if_path_matches do
6
+ # Don't serve is data is not a string.
7
+ return unless data.is_a?(String)
7
8
 
8
- # Don't serve is data is not a string.
9
- return unless data.is_a?(String)
9
+ # Mix in default options
10
+ options = {
11
+ :layout => context.layout
12
+ }.merge(options)
10
13
 
11
- # Mix in default options
12
- options = {
13
- :layout => context.layout
14
- }.merge(options)
14
+ # Add status code from options
15
+ response.status = options.delete(:status) if options.has_key?(:status)
15
16
 
16
- # Add status code from options
17
- response.status = options.delete(:status) if options.has_key?(:status)
17
+ # Extract layout
18
+ layout = options.delete(:layout)
18
19
 
19
- # Extract layout
20
- layout = options.delete(:layout)
20
+ # Treat remaining options as headers
21
+ options.each { |k, v| header k, v }
21
22
 
22
- # Treat remaining options as headers
23
- options.each { |k, v| header k, v }
23
+ # Apply layout, if available
24
+ if layout
25
+ data = render(layout) { data }
26
+ end
24
27
 
25
- # Apply layout, if available
26
- if layout
27
- data = render(layout) { data }
28
+ # Set response body and finish request
29
+ response.body = [data]
30
+ halt!
28
31
  end
29
-
30
- # Set response body and finish request
31
- response.body = [data]
32
- halt!
33
- end
34
-
35
- def serve_or_404!(*args)
36
- serve!(*args)
37
-
38
- # If we get here, #serve! decided not to serve, so let's raise a 404.
39
- raise Errors::NotFound
40
32
  end
41
33
 
42
34
  def halt!(message = :done)
43
- throw message
35
+ only_if_path_matches do
36
+ throw message
37
+ end
44
38
  end
45
39
 
46
40
  def redirect!(to, status = 302)
47
- header :location, url_for(to)
48
- response.status = status
49
- halt!
41
+ only_if_path_matches do
42
+ header :location, url_for(to)
43
+ response.status = status
44
+ halt!
45
+ end
50
46
  end
51
47
 
52
48
  def layout(name)
@@ -87,13 +83,24 @@ module Happy
87
83
  elsif thing.respond_to?(:call)
88
84
  # Rack apps!
89
85
  context.response = thing.call(request.env)
90
- halt!
86
+ throw :done
91
87
  elsif thing.respond_to?(:to_s)
92
88
  thing.to_s
93
89
  else
94
90
  raise "Don't know how to run #{thing.inspect} :("
95
91
  end
96
92
  end
93
+
94
+
95
+ private
96
+
97
+ # Execute the provided block, unless there are still bits of
98
+ # unprocessed path left (which indicates that the current path
99
+ # is not the path the user requested.)
100
+ #
101
+ def only_if_path_matches
102
+ yield if remaining_path.empty?
103
+ end
97
104
  end
98
105
  end
99
106
  end
@@ -0,0 +1,21 @@
1
+ module Happy
2
+ class Controller
3
+ module Configurable
4
+ extend ActiveSupport::Concern
5
+
6
+ def config
7
+ self.class.config
8
+ end
9
+
10
+ module ClassMethods
11
+ def config
12
+ @config ||= {}
13
+ end
14
+
15
+ def set(k, v)
16
+ config[k.to_sym] = v
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,19 +3,26 @@ module Happy
3
3
  module Rackable
4
4
  extend ActiveSupport::Concern
5
5
 
6
- def call(env)
7
- @env = env
8
-
6
+ def handle_request
9
7
  catch :done do
10
- serve_or_404! perform
8
+ serve!(perform) or raise Errors::NotFound
11
9
  end
12
10
 
13
11
  response
12
+ rescue Errors::NotFound => e
13
+ html = Errors.html e, env,
14
+ :title => "Path not found",
15
+ :message => '',
16
+ :friendly_message => "You performed a <strong>#{context.request.request_method}</strong> request on <strong>#{context.request.path}</strong>, but your application did not know how to handle this request."
17
+ [404, {'Content-type' => 'text/html'}, [html]]
18
+ rescue ::Exception => e
19
+ html = Errors.html e, env
20
+ [500, {'Content-type' => 'text/html'}, [html]]
14
21
  end
15
22
 
16
23
  module ClassMethods
17
24
  def call(env)
18
- new.call(env)
25
+ new(env).handle_request
19
26
  end
20
27
  end
21
28
  end
@@ -34,7 +34,7 @@ module Happy
34
34
  previous_path << remaining_path.shift
35
35
  end
36
36
 
37
- serve_or_404! instance_exec(&blk)
37
+ serve!(instance_exec(&blk)) or raise Errors::NotFound
38
38
  end
39
39
  end
40
40
  end
@@ -1,12 +1,19 @@
1
1
  require 'happy/controller/routing'
2
2
  require 'happy/controller/actions'
3
3
  require 'happy/controller/rackable'
4
+ require 'happy/controller/configurable'
4
5
 
5
6
  module Happy
7
+ # Base class for Happy controllers. A controller's primary job is to act
8
+ # upon an incoming request, navigating the request URL's path, and finally
9
+ # deciding on a course of action (eg. rendering something, redirecting the
10
+ # client, passing control over to another controller, and so on.)
11
+ #
6
12
  class Controller
7
13
  include Routing
8
14
  include Actions
9
15
  include Rackable
16
+ include Configurable
10
17
 
11
18
  attr_reader :options, :env, :root_path
12
19
 
@@ -15,6 +22,15 @@ module Happy
15
22
  :render, :url_for,
16
23
  :to => :context
17
24
 
25
+ # Creates a new instance of {Controller}. When a block is provided,
26
+ # it is run against the new instance, allowing custom controller classes
27
+ # to provide DSL-like configuration.
28
+ #
29
+ # @param env [Hash]
30
+ # Rack environment hash.
31
+ # @param options [Hash]
32
+ # Controller options.
33
+ #
18
34
  def initialize(env = {}, options = {}, &blk)
19
35
  @env = env
20
36
  @options = options
@@ -27,14 +43,16 @@ module Happy
27
43
  instance_exec(&blk) if blk
28
44
  end
29
45
 
46
+ protected
47
+
48
+ # Run this controller, performing its routing logic.
49
+ #
30
50
  def perform
31
51
  context.with_controller(self) do
32
52
  route
33
53
  end
34
54
  end
35
55
 
36
- protected
37
-
38
56
  def root_url(extras = nil)
39
57
  url_for(root_path, extras)
40
58
  end
@@ -46,22 +64,12 @@ module Happy
46
64
  end
47
65
 
48
66
  def context
49
- @env['happy.context'] ||= Happy::Context.from_env(@env)
67
+ @env['happy.context'] ||= Happy::Context.new(@env)
50
68
  end
51
69
 
52
70
  def route
53
71
  # override this in subclasses
54
72
  end
55
73
 
56
- class << self
57
- # Create a new subclass of Happy::Controller, using the provided
58
- # block for defining class methods et al.
59
- #
60
- def build(&blk)
61
- Class.new(self).tap do |klass|
62
- klass.class_eval(&blk) if blk
63
- end
64
- end
65
- end
66
74
  end
67
75
  end
@@ -0,0 +1,64 @@
1
+ module Happy
2
+ module Errors
3
+ class Base < StandardError ; end
4
+ class NotFound < Base ; end
5
+
6
+ # Render a HTML page for the given exception.
7
+ #
8
+ # @param [Exception] exception
9
+ # The exception to display.
10
+ # @param [Hash] env
11
+ # The current Rack environment hash (used to display information on request parameters, session contents and such.)
12
+ #
13
+ # @option options [String] :title
14
+ # Title of error page
15
+ # @option options [String] :message
16
+ # Message to be displayed on error page, right underneath the title.
17
+ # @option options [String] :friendly_message
18
+ # Friendly error message to be displayed below title and message.
19
+ # If left blank, will be generated from the exception message.
20
+ #
21
+ def self.html(exception, env, options = {})
22
+ options = {
23
+ :title => exception.class.to_s,
24
+ :message => exception.message,
25
+ :friendly_message => nil
26
+ }.merge(options)
27
+
28
+ context = env['happy.context']
29
+
30
+ # Load and cache error template.
31
+ @html = begin
32
+ File.read(File.expand_path(File.join(__FILE__, '../files/error.erb')))
33
+ end
34
+
35
+ # Generate friendly message from exception.
36
+ options[:friendly_message] ||= friendly_message_for options[:message]
37
+
38
+ # Render error page.
39
+ ERB.new(@html).result(binding)
40
+ end
41
+
42
+ protected
43
+
44
+ def self.friendly_message_for(msg)
45
+ case msg
46
+ when /^undefined local variable or method `(.+)'/
47
+ "You called a method called \"#{$1}\", and this method did not exist. This could simply be a typo. If it's not, please check that you're calling the method from within the correct scope."
48
+ when /^undefined method `(.+)' for nil:NilClass$/
49
+ "You called a method called <strong>\"#{$1}\"</strong> on <strong>nil</strong>. In most cases, this is due to simple typos; please check your variable names. Otherwise, make sure the receiving object has been initialized correctly."
50
+ when /^undefined method `(.+)' for (.+)$/
51
+ method = $1
52
+ var = $2
53
+ klass = case var
54
+ when /^#<(.+):0x.+>$/ then $1
55
+ when /^.+:(.+)$/ then $1
56
+ else var
57
+ end
58
+ "You called a method called <strong>\"#{h method}\"</strong> on an instance of class <strong>#{h klass}</strong>, which doesn't know how to respond to that method. Please check for typos."
59
+ end
60
+ end
61
+
62
+ def self.h(t) ; Rack::Utils.escape_html(t) ; end
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ module Happy
2
+ module Extras
3
+ class CodeReloader < Happy::Controller
4
+ class << self
5
+ def reload_app_code
6
+ Dir[config[:directory]].each do |f|
7
+ load f
8
+ end
9
+ @app_code_loaded = true
10
+ end
11
+
12
+ def reload_app_code?
13
+ Happy.env.development? || !@app_code_loaded
14
+ end
15
+ end
16
+
17
+ def route
18
+ raise "no directory specified" unless config[:directory]
19
+ raise "no controller specified" unless config[:controller]
20
+
21
+ self.class.reload_app_code if self.class.reload_app_code?
22
+ run eval(config[:controller])
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,131 @@
1
+ <html>
2
+ <head>
3
+ <style>
4
+ body {
5
+ font: 18px/24px "Helvetica Neue",Arial,Helvetica,sans-serif;
6
+ color: #555;
7
+ background-color: #fffef8;
8
+ padding: 30px 0 100px 0;
9
+ }
10
+ .container {
11
+ width: 800px;
12
+ margin: 0 auto;
13
+ }
14
+ h1, h2, h3 {
15
+ color: #222;
16
+ }
17
+ h1 {
18
+ margin: 0 0 0px -4px;
19
+ font-size: 80px;
20
+ line-height: 80px;
21
+ letter-spacing: -0.05em;
22
+ text-shadow: 2px 1px 4px rgba(0, 0, 0, 0.2);
23
+ }
24
+ h2 {
25
+ margin-bottom: 0;
26
+ margin-top: 2em;
27
+ text-shadow: 2px 1px 4px rgba(0, 0, 0, 0.1);
28
+ }
29
+ h3 {
30
+ margin-bottom: 0;
31
+ color: #999;
32
+ }
33
+ p.message {
34
+ margin-top: 0px !important;
35
+ font-size: 30px;
36
+ line-height: 40px;
37
+ margin: 20px 0;
38
+ }
39
+ .friendly_message {
40
+ font-size: 20px;
41
+ line-height: 30px;
42
+ color: #777;
43
+ margin: 20px 0;
44
+ }
45
+ code {
46
+ font-family: Menlo,Monaco,"Lucida Console",Consolas,"Courier New",monotype;
47
+ }
48
+ .output {
49
+ display: block;
50
+ width: 820px;
51
+ margin-left: -20px;
52
+
53
+ background-color: #222;
54
+ color: #ccc;
55
+ padding: 20px;
56
+ border-radius: 15px;
57
+ margin-top: 1em;
58
+
59
+ font: 14px/20px Menlo,Monaco,"Lucida Console",Consolas,"Courier New",monotype;
60
+ }
61
+ .backtrace {
62
+ list-style: none;
63
+ height: 192px;
64
+ overflow: auto;
65
+ }
66
+ .backtrace li.app { color: #fff; }
67
+ .backtrace li.ruby { color: #c55; }
68
+ .backtrace li.happy { color: #5c5; }
69
+ .backtrace .where { font-weight: bold; }
70
+ .backtrace .location { color: #666; }
71
+ </style>
72
+ </head>
73
+ <body>
74
+ <div class="container">
75
+ <h1><%= h options[:title] %></h1>
76
+
77
+ <p class="message">
78
+ <%= h options[:message] %>
79
+ </p>
80
+
81
+ <% if options[:friendly_message] %>
82
+ <p class="friendly_message">
83
+ <%= options[:friendly_message] %>
84
+ </p>
85
+ <% end %>
86
+
87
+ <h2>Backtrace:</h2>
88
+ <ul class="output backtrace">
89
+ <% exception.backtrace.each do |l| %>
90
+ <%
91
+ file, line, where = l.split(':')
92
+
93
+ klass = case file
94
+ when %r{happy/lib/happy} then 'happy'
95
+ when %r{lib/ruby/gems} then 'ruby'
96
+ else 'app'
97
+ end
98
+ %>
99
+ <% where =~ /^in `(.+)'$/ %>
100
+ <li class="<%= klass %>">
101
+ <span class="where">
102
+ <%= h ($1 || where) %>
103
+ </span>
104
+ <span class="location">
105
+ @ <%= h file %>:<%= h line %>
106
+ </span>
107
+ </li>
108
+ <% end %>
109
+ </ul>
110
+
111
+ <h2>Request Parameters:</h2>
112
+ <div class="output params">
113
+ <%= h context.request.params.inspect %>
114
+ </div>
115
+
116
+ <h2>Session:</h2>
117
+ <div class="output session">
118
+ <%= h context.request.session.inspect %>
119
+ </div>
120
+
121
+ <h2>Environment:</h2>
122
+ <div class="output env">
123
+ <%= h env %>
124
+ </div>
125
+
126
+ <p>
127
+ If you need help, please drop by <code>#happy</code> on FreeNode.
128
+ </p>
129
+ </div>
130
+ </body>
131
+ </html>
data/lib/happy/request.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  # SMELL: really?
2
2
  require 'happy-helpers/utils/date_parameter_converter'
3
3
 
4
- # SMELL: do we really need our own request class?
5
-
6
4
  module Happy
5
+ # Happy's own little request class. It extends {Rack::Request} with
6
+ # a bit of convenience functionality.
7
+ #
7
8
  class Request < Rack::Request
9
+
8
10
  protected
9
11
 
10
12
  def parse_query(qs)
data/lib/happy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Happy
2
- VERSION = "0.1.0.pre16"
2
+ VERSION = "0.1.0.pre19"
3
3
  end
data/lib/happy.rb CHANGED
@@ -1,14 +1,10 @@
1
1
  require 'rack'
2
2
  require 'happy/version'
3
+ require 'happy/errors'
3
4
  require 'happy/context'
4
5
  require 'happy/controller'
5
6
 
6
7
  module Happy
7
- module Errors
8
- class Base < StandardError ; end
9
- class NotFound < Base ; end
10
- end
11
-
12
8
  def self.env
13
9
  ActiveSupport::StringInquirer.new(ENV['RACK_ENV'] || 'development')
14
10
  end
@@ -33,3 +29,6 @@ module Happy
33
29
  @last_controller_class_created.try(:call, env) or raise "Please use Happy.route to define some routes."
34
30
  end
35
31
  end
32
+
33
+ __END__
34
+ yooooooo!
@@ -40,6 +40,19 @@ module Happy
40
40
  it "finishes the rendering by throwing :done" do
41
41
  expect { subject.serve! "body" }.to throw_symbol :done
42
42
  end
43
+
44
+ it "doesn't do anything if the current path does not match the request path" do
45
+ def app
46
+ Happy.route do
47
+ serve! "This should not render"
48
+ path 'test' do
49
+ serve! "But this should render"
50
+ end
51
+ end
52
+ end
53
+
54
+ response_for { get '/test' }.body.should == "But this should render"
55
+ end
43
56
  end
44
57
 
45
58
  describe '#redirect!' do
@@ -61,6 +74,22 @@ module Happy
61
74
  get '/'
62
75
  last_response.status.should == 301
63
76
  end
77
+
78
+ it "doesn't do anything if the current path does not match the request path" do
79
+ def app
80
+ Happy.route do
81
+ redirect! "http://mans.de"
82
+
83
+ path 'test' do
84
+ redirect! "http://schnitzelpress.org"
85
+ end
86
+ end
87
+ end
88
+
89
+ get '/test'
90
+ last_response.should be_redirect
91
+ last_response.headers['Location'].should == 'http://schnitzelpress.org'
92
+ end
64
93
  end
65
94
 
66
95
  describe '#run' do
@@ -18,25 +18,6 @@ module Happy
18
18
  last_response.body.should == 'it works'
19
19
  end
20
20
 
21
- describe ".build" do
22
- subject do
23
- Controller.build do
24
- def route
25
- serve! "yay!"
26
- end
27
- end
28
- end
29
-
30
- it "creates a new controller class" do
31
- subject.ancestors.should include(Controller)
32
- end
33
-
34
- it "should use the passed block to initialize the new controller class" do
35
- get "/"
36
- last_response.body.should == 'yay!'
37
- end
38
- end
39
-
40
21
  describe '#url' do
41
22
  it "returns the current URL" do
42
23
  def app
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: happy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre16
4
+ version: 0.1.0.pre19
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-07 00:00:00.000000000 Z
12
+ date: 2012-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70251874709220 !ruby/object:Gem::Requirement
16
+ requirement: &70302468087940 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70251874709220
24
+ version_requirements: *70302468087940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rack
27
- requirement: &70251874706120 !ruby/object:Gem::Requirement
27
+ requirement: &70302468086760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,21 +32,21 @@ dependencies:
32
32
  version: '1.4'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70251874706120
35
+ version_requirements: *70302468086760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: happy-helpers
38
- requirement: &70251874722540 !ruby/object:Gem::Requirement
38
+ requirement: &70302468085720 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
42
42
  - !ruby/object:Gem::Version
43
- version: 0.1.0.pre9
43
+ version: 0.1.0.pre10
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70251874722540
46
+ version_requirements: *70302468085720
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: allowance
49
- requirement: &70251874720680 !ruby/object:Gem::Requirement
49
+ requirement: &70302468084660 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.1.1
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70251874720680
57
+ version_requirements: *70302468084660
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: happy-cli
60
- requirement: &70251874719340 !ruby/object:Gem::Requirement
60
+ requirement: &70302468122420 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.1.0.pre1
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70251874719340
68
+ version_requirements: *70302468122420
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
- requirement: &70251874718000 !ruby/object:Gem::Requirement
71
+ requirement: &70302468120940 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70251874718000
79
+ version_requirements: *70302468120940
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec
82
- requirement: &70251874735320 !ruby/object:Gem::Requirement
82
+ requirement: &70302468119720 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '2.8'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70251874735320
90
+ version_requirements: *70302468119720
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rspec-html-matchers
93
- requirement: &70251874732880 !ruby/object:Gem::Requirement
93
+ requirement: &70302468119000 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70251874732880
101
+ version_requirements: *70302468119000
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rack-test
104
- requirement: &70251874731140 !ruby/object:Gem::Requirement
104
+ requirement: &70302468118500 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70251874731140
112
+ version_requirements: *70302468118500
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: watchr
115
- requirement: &70251874727440 !ruby/object:Gem::Requirement
115
+ requirement: &70302468118060 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,7 +120,7 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70251874727440
123
+ version_requirements: *70302468118060
124
124
  description: A happy little toolkit for writing web applications.
125
125
  email:
126
126
  - hendrik@mans.de
@@ -143,12 +143,16 @@ files:
143
143
  - lib/happy/context/helpers.rb
144
144
  - lib/happy/controller.rb
145
145
  - lib/happy/controller/actions.rb
146
+ - lib/happy/controller/configurable.rb
146
147
  - lib/happy/controller/rackable.rb
147
148
  - lib/happy/controller/routing.rb
149
+ - lib/happy/errors.rb
150
+ - lib/happy/extras/code_reloader.rb
148
151
  - lib/happy/extras/permissions.rb
149
152
  - lib/happy/extras/resources.rb
150
153
  - lib/happy/extras/scriptable.rb
151
154
  - lib/happy/extras/static.rb
155
+ - lib/happy/files/error.erb
152
156
  - lib/happy/request.rb
153
157
  - lib/happy/version.rb
154
158
  - spec/controller/actions_spec.rb