jeanine 0.4.0 → 0.7.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: d62b1858b952c8c8b7575f4a5c8ff60d9401e846d6d9fe9d302573052715706c
4
- data.tar.gz: fd9d260653e2164bd98fc333dedcbfedf1e58fd0f7feb33d84435406668a76df
2
+ SHA1:
3
+ metadata.gz: 00f439386000e4e03fde175cf305429a84809cc0
4
+ data.tar.gz: 2c19abd0a152c6240c2e57beb0cf3cedf520ed93
5
5
  SHA512:
6
- metadata.gz: bcfb247647f312eb473cf7681b1415dd7cdd828f545711cdb5e7cf641c69127d832617e952ece9f83daf1c09e391624efc70acd7259aa3ad1d168a01b93aa135
7
- data.tar.gz: 6afa5f33deb9c2a2094e317bdd5b755aa184a97c7378da944cc73968c4069d17b3e8c37b8f996efb7cd81b8af115aaed13406e45afd9bd5e1382225513c44bbc
6
+ metadata.gz: 205ed5845e02c18b59014cc5616f0fadc0f67b448a45c0cfcded08af17516a7e0b1beba07cb107a2a9dda2232b6404112b65dda00aecf0b97569df44bb15a030
7
+ data.tar.gz: 0f4fff626a3151825c605026bb68cafcf701aa05753fb06ac76086fc79f7b9e83ce975a51d4fc161e75cd0672dcfde975b4b4bcd343113923754a24ef09e5c19
@@ -0,0 +1,228 @@
1
+ # Jeanine
2
+
3
+ A Ruby micro-web-framework that gives you enough training wheels to be productive, while being as nearly as fast as Rack itself.
4
+
5
+ Its design (and some parts of the code) is influenced by/inherited from (thanks!) Ruby on Rails, Rack::App, Hobbit, and Cuba. Without them this is nothing.
6
+
7
+ ## Name
8
+
9
+ Named after my mom. Because she was the best.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'jeanine'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install jeanine
26
+
27
+ ## Basic usage
28
+
29
+ Drop this into `config.ru`:
30
+
31
+ ```ruby
32
+ require 'bundler/setup'
33
+ require 'jeanine'
34
+
35
+ class App < Jeanine::App
36
+ root do
37
+ "Hello world"
38
+ end
39
+ end
40
+
41
+ run App
42
+ ```
43
+
44
+ `$ rackup`
45
+
46
+ ## Advanced usage
47
+
48
+ ```ruby
49
+ class App < Jeanine::App
50
+ path "/posts" do
51
+ get do
52
+ if request.json?
53
+ render json: []
54
+ else
55
+ "Posts index"
56
+ end
57
+ end
58
+ get "new" do
59
+ "Posts new"
60
+ end
61
+ post do
62
+ "Posts post"
63
+ end
64
+ path ":id" do
65
+ get do
66
+ "Posts #{params[:id]}"
67
+ end
68
+ match via: [:put, :patch] do
69
+ "Posts #{request.via} #{params[:id]}"
70
+ end
71
+ delete do
72
+ "Posts delete #{params[:id]}"
73
+ end
74
+ path "/comments" do
75
+ get do
76
+ "Posts #{params[:id]} comments"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ ```
83
+
84
+ ## Plugins
85
+
86
+ ### Callbacks
87
+
88
+ Supports `before` and `after` callbacks (same DSL):
89
+
90
+ ```
91
+ class App < Jeanine::App
92
+ plugin :Callbacks
93
+ before do
94
+ puts "All"
95
+ end
96
+ before /posts/ do
97
+ puts "Before posts"
98
+ end
99
+ before /posts\/\d*/, /comments\/\d*/ do
100
+ puts "Before posts/:id, comments/:id"
101
+ response.headers['X-Thing-Id'] = params[:id]
102
+ end
103
+ end
104
+ ```
105
+
106
+ ### Rendering
107
+
108
+ Basic support for rendering. Be explicit.
109
+
110
+ ```ruby
111
+ class App < Jeanine::App
112
+ plugin :Rendering
113
+ # loads views/root.html.erb and views/layouts/application.html.erb
114
+ root do
115
+ @title = "My cool app"
116
+ render template: "root.html.erb", layout: "application.html.erb"
117
+ end
118
+ end
119
+ ```
120
+
121
+ ### Sessions
122
+
123
+ Uses Rack's session management.
124
+
125
+ ```ruby
126
+ class App < Jeanine::App
127
+ plugin :Session
128
+ root do
129
+ session[:uid] = SecureRandom.hex
130
+ end
131
+ end
132
+ ```
133
+
134
+ ### Error handling
135
+
136
+ ```ruby
137
+ class App < Jeanine::App
138
+ plugin :Resucable
139
+ rescue_from NoMethodError, RuntimeError do |exception|
140
+ response.status = 500
141
+ "Oh no!"
142
+ end
143
+ rescue_from StandardError, with: :handle_error!
144
+ root do
145
+ @title = "My cool app"
146
+ raise NoMethodError
147
+ render template: "root.html.erb", layout: "application.html.erb"
148
+ end
149
+
150
+ private
151
+
152
+ def handle_error!(exception)
153
+ response.status = 500
154
+ render template: "error.html.erb"
155
+ end
156
+ end
157
+ ```
158
+
159
+ ## Development
160
+
161
+ ### Ideologies
162
+
163
+ * No meaningless metaprogramming = fast
164
+
165
+ ## Benchmarks
166
+
167
+ ### Requests/second
168
+
169
+ Benched on a Intel Core i7-8700B / 64GB RAM.
170
+
171
+ ```
172
+ Framework Requests/sec % from best
173
+ ----------------------------------------------
174
+ rack 17299.31 100.00%
175
+ jeanine 16022.71 92.62%
176
+ rack-response 15462.50 89.38%
177
+ syro 15416.13 89.11%
178
+ watts 15307.52 88.49%
179
+ roda 14550.56 84.11%
180
+ hanami-router 14342.92 82.91%
181
+ cuba 14246.23 82.35%
182
+ hobbit 14132.20 81.69%
183
+ rambutan 12526.40 72.41%
184
+ rack-app 11696.66 67.61%
185
+ flame 7931.61 45.85%
186
+ rails-metal 7761.75 44.87%
187
+ sinatra 4616.81 26.69%
188
+ grape 2401.66 13.88%
189
+ hobby 1805.93 10.44%
190
+ rails-api 1593.77 9.21%
191
+ ```
192
+
193
+ ### Memory
194
+
195
+ ```
196
+ Framework Allocs/Req Memsize/Req
197
+ --------------------------------------
198
+ rack 40 3408
199
+ roda 43 4016
200
+ syro 44 4288
201
+ cuba 44 4056
202
+ watts 46 3648
203
+ hobbit 48 4416
204
+ jeanine 52 4576
205
+ hobby 52 5416
206
+ rack-response 55 5128
207
+ rails-metal 59 5848
208
+ hanami-router 63 5184
209
+ rambutan 79 6944
210
+ rack-app 80 8424
211
+ flame 115 9648
212
+ sinatra 179 13440
213
+ grape 250 26704
214
+ rails-api 383 34949
215
+ ```
216
+
217
+ ## Todo
218
+
219
+ * Callback constraints
220
+ * File downloads
221
+
222
+ ## Contributing
223
+
224
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joshmn/jeanine.
225
+
226
+ ## License
227
+
228
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/jeanine/cli'
4
+
5
+ Jeanine::CLI.new(ARGV).execute
@@ -1,18 +1,14 @@
1
+ require 'rack'
2
+
1
3
  require 'forwardable'
2
4
  require 'logger'
3
5
 
4
6
  require "jeanine/version"
5
7
  require 'jeanine/core_ext'
6
- require 'jeanine/router'
7
- require 'jeanine/app'
8
- require 'tilt'
9
8
 
10
9
  module Jeanine
11
- def self.view_paths
12
- @_view_paths ||= Set.new(["views"])
13
- end
14
- def self.tilt_cache
15
- @title_cache ||= Tilt::Cache.new
10
+ def self._installed_plugins
11
+ @_installed_plugins ||= []
16
12
  end
17
13
 
18
14
  def self.logger
@@ -26,4 +22,7 @@ module Jeanine
26
22
  def self.router
27
23
  @router ||= Router.new
28
24
  end
25
+
26
+ autoload :Router, 'jeanine/router'
27
+ autoload :App, 'jeanine/app'
29
28
  end
@@ -1,26 +1,35 @@
1
- require 'jeanine/callbacks'
2
1
  require 'jeanine/mimes'
3
2
  require 'jeanine/request'
4
- require 'jeanine/rescuing'
5
3
  require 'jeanine/response'
6
- require 'jeanine/renderer'
7
4
  require 'jeanine/routing'
8
- require 'jeanine/session'
9
- require 'jeanine/view_paths'
10
5
 
11
6
  module Jeanine
12
7
  class App
13
- include Session
14
- include Rescuing
15
8
  include Routing::Evaluation
16
9
 
17
10
  attr_reader :request, :response
18
11
 
12
+ def self.plugin(name)
13
+ unless Jeanine._installed_plugins.include?(name)
14
+ unless const_defined?("Jeanine::#{name}")
15
+ require "jeanine/#{name.to_s.underscore}"
16
+ end
17
+ include Kernel.const_get("Jeanine::#{name}")
18
+ Jeanine._installed_plugins << name
19
+ end
20
+ end
21
+
22
+ def self.installed_plugins
23
+ Jeanine._installed_plugins
24
+ end
25
+
26
+ # plugin :Callbacks
27
+ # plugin :Rendering
28
+ # plugin :Rescuing
29
+ # plugin :Session
30
+
19
31
  class << self
20
- include Callbacks
21
32
  include Routing::DSL
22
- include Rescuing
23
- include ViewPaths
24
33
 
25
34
  alias :_new :new
26
35
  def new(*args, &block)
@@ -47,21 +56,10 @@ module Jeanine
47
56
  end
48
57
 
49
58
  def call(env)
50
- begin
51
- @env = env
52
- @request = Jeanine::Request.new(env)
53
- @response = Jeanine::Response.new
54
- catch(:halt) { route_eval }
55
- rescue => error
56
- handler = self.class.rescue_handlers[error.class]
57
- raise error unless handler
58
- if handler.is_a?(Symbol)
59
- @response.write(send(handler, error))
60
- else
61
- @response.write(instance_exec(error, &handler))
62
- end
63
- @response.complete!
64
- end
59
+ @env = env
60
+ @request = Jeanine::Request.new(env)
61
+ @response = Jeanine::Response.new
62
+ catch(:halt) { route_eval }
65
63
  end
66
64
 
67
65
  private
@@ -74,11 +72,6 @@ module Jeanine
74
72
  end
75
73
  end
76
74
 
77
- def render(*args)
78
- @response.action_variables = instance_variables_cache
79
- Renderer.new(@response).render(*args)
80
- end
81
-
82
75
  def instance_variables_cache
83
76
  instance_variables.each_with_object({}) do |var, obj|
84
77
  obj[var] = instance_variable_get(var)
@@ -1,28 +1,105 @@
1
1
  module Jeanine
2
2
  module Callbacks
3
- def _callbacks
4
- @_callbacks ||= {
5
- before: [],
6
- after: [],
7
- before_all: [],
8
- after_all: []
9
- }
3
+ def self.included(klass)
4
+ klass.extend InstanceMethods
5
+ klass.prepend EvaluationMethods
10
6
  end
11
7
 
12
- def before(*paths, &block)
13
- _register_callback(:before, paths, &block)
14
- end
8
+ module InstanceMethods
9
+ def _callbacks
10
+ @_callbacks ||= {
11
+ before: [],
12
+ after: [],
13
+ before_all: [],
14
+ after_all: []
15
+ }
16
+ end
17
+
18
+ def before(*paths, &block)
19
+ _register_callback(:before, paths, &block)
20
+ end
21
+
22
+ def after(*paths, &block)
23
+ _register_callback(:after, paths, &block)
24
+ end
25
+
26
+ private
15
27
 
16
- def after(*paths, &block)
17
- _register_callback(:after, paths, &block)
28
+ def _register_callback(type, paths = [], &block)
29
+ if paths == []
30
+ _callbacks["#{type}_all".to_sym] << { block: block }
31
+ else
32
+ _callbacks[type] << { paths: paths, block: block }
33
+ end
34
+ end
18
35
  end
19
36
 
20
- private
21
- def _register_callback(type, paths = [], &block)
22
- if paths == []
23
- _callbacks["#{type}_all".to_sym] << { block: block }
24
- else
25
- _callbacks[type] << { paths: paths, block: block }
37
+ module EvaluationMethods
38
+ def route_eval
39
+ before_find_route!
40
+ route = find_route
41
+
42
+ if route
43
+ before_evaluate_route!
44
+ result = instance_eval(&route[:block])
45
+ @response.write(result)
46
+ after_evaluate_route!
47
+ else
48
+ @response.status = 404
49
+ end
50
+ after_response!
51
+ @response.complete!
52
+ end
53
+
54
+ private
55
+
56
+ def before_find_route!
57
+ run_before_callbacks!(:before_all)
58
+ end
59
+
60
+ def before_evaluate_route!
61
+ run_before_callbacks!(:before)
62
+ end
63
+
64
+ def after_evaluate_route!
65
+ run_after_callbacks!(:after)
66
+ end
67
+
68
+ def after_response!
69
+ run_after_callbacks!(:after_all)
70
+ end
71
+
72
+ def run_before_callbacks!(type)
73
+ if type == :before_all
74
+ self.class._callbacks[type].each { |callback| eval_callback(&callback[:block]) }
75
+ else
76
+ matching_callbacks(type) do |callback|
77
+ eval_callback(&callback[:block])
78
+ end
79
+ end
80
+ end
81
+
82
+ def run_after_callbacks!(type)
83
+ if type == :after_all
84
+ self.class._callbacks[type].each { |callback| eval_callback(&callback[:block]) }
85
+ else
86
+ matching_callbacks(type) do |callback|
87
+ eval_callback(&callback[:block])
88
+ end
89
+ end
90
+ end
91
+
92
+ def matching_callbacks(type)
93
+ self.class._callbacks[type].select do |callback|
94
+ paths = callback[:paths]
95
+ if paths.detect { |path| path.match?(@request.path_info) }
96
+ yield callback
97
+ end
98
+ end
99
+ end
100
+
101
+ def eval_callback(*args, &callback)
102
+ instance_exec(*args, &callback)
26
103
  end
27
104
  end
28
105
  end
@@ -0,0 +1,32 @@
1
+ require 'fileutils'
2
+
3
+ module Jeanine
4
+ class CLI
5
+ def initialize(args)
6
+ @args = args
7
+ end
8
+
9
+ def execute
10
+ if @args[0] == 'new'
11
+ command_new!
12
+ else
13
+ $stdout.puts "I don't know how to `#{@args[0]}`. Maybe you meant `new`?"
14
+ end
15
+ end
16
+
17
+ def command_new!
18
+ FileUtils.mkdir("#{@args[1]}") unless Dir.exists?("#{@args[1]}")
19
+ FileUtils.mkdir("#{@args[1]}/config") unless Dir.exists?("#{@args[1]}/config")
20
+ relative_dir = "lib/jeanine/generator/new"
21
+ Dir.glob("lib/jeanine/generator/new/**/*.*").each do |file|
22
+ new_dir = file.gsub(relative_dir, "#{@args[1]}")[0...-3]
23
+ FileUtils.copy_file(file, new_dir)
24
+ end
25
+ relative_dir = "lib/jeanine/generator/new/config"
26
+ Dir.glob("lib/jeanine/generator/new/config/**/*.*").each do |file|
27
+ new_dir = file.gsub(relative_dir, "#{@args[1]}/config")[0...-3]
28
+ FileUtils.copy_file(file, new_dir)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,4 +5,19 @@ class Hash
5
5
  def reverse_merge!(other_hash)
6
6
  replace(reverse_merge(other_hash))
7
7
  end
8
+ def deep_transform_keys(&block)
9
+ result = {}
10
+ each do |key, value|
11
+ result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
12
+ end
13
+ result
14
+ end
15
+
16
+ def deep_transform_keys!(&block)
17
+ keys.each do |key|
18
+ value = delete(key)
19
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
20
+ end
21
+ self
22
+ end
8
23
  end
@@ -3,4 +3,11 @@ class String
3
3
  return nil if self.empty?
4
4
  self
5
5
  end
6
+ def underscore
7
+ self.gsub(/::/, '/').
8
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
9
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
10
+ tr("-", "_").
11
+ downcase
12
+ end
6
13
  end
@@ -1,18 +1,16 @@
1
1
  module Broding
2
- module Environment
3
- def env
4
- @_env ||= (ENV["RACK_ENV"].presence || "development")
5
- end
2
+ def env
3
+ @_env ||= (ENV["RACK_ENV"].presence || "development")
4
+ end
6
5
 
7
- def groups(*groups)
8
- hash = groups.extract_options!
9
- env = Jeanine.env
10
- groups.unshift(:default, env)
11
- groups.concat ENV["BRODY_GROUPS"].to_s.split(",")
12
- groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) }
13
- groups.compact!
14
- groups.uniq!
15
- groups
16
- end
6
+ def groups(*groups)
7
+ hash = groups.extract_options!
8
+ env = Jeanine.env
9
+ groups.unshift(:default, env)
10
+ groups.concat ENV["BRODY_GROUPS"].to_s.split(",")
11
+ groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) }
12
+ groups.compact!
13
+ groups.uniq!
14
+ groups
17
15
  end
18
16
  end
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby "$RUBY_VERSION$"
4
+
5
+ gem "jeanine"
6
+
7
+ group :production do
8
+ gem "puma"
9
+ end
@@ -0,0 +1,8 @@
1
+ # README
2
+
3
+ Welcome to your Jeanine app.
4
+
5
+ ## Start
6
+
7
+ `$ bundle`
8
+ `$ rackup`
@@ -0,0 +1,10 @@
1
+ require_relative 'boot'
2
+
3
+ require 'jeanine'
4
+
5
+ # Require the gems listed in Gemfile, including any gems
6
+ # you've limited to :test, :development, or :production.
7
+ Bundler.require(*Jeanine.groups)
8
+
9
+ class App < ::Jeanine::App
10
+ end
@@ -0,0 +1,3 @@
1
+ require_relative './app'
2
+
3
+ run App
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
4
+
5
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
@@ -0,0 +1 @@
1
+ require_relative '../app'
@@ -0,0 +1,35 @@
1
+ # Puma can serve each request in a thread from an internal thread pool.
2
+ # The `threads` method setting takes two numbers: a minimum and maximum.
3
+ # Any libraries that use thread pools should be configured to match
4
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
5
+ # and maximum; this matches the default thread size of Active Record.
6
+ #
7
+ max_threads_count = ENV.fetch("RACK_MAX_THREADS") { 5 }
8
+ min_threads_count = ENV.fetch("RACK_MIN_THREADS") { max_threads_count }
9
+ threads min_threads_count, max_threads_count
10
+
11
+ # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
12
+ #
13
+ port ENV.fetch("PORT") { 3000 }
14
+
15
+ # Specifies the `environment` that Puma will run in.
16
+ #
17
+ environment ENV.fetch("RACK_ENV") { "development" }
18
+
19
+ # Specifies the `pidfile` that Puma will use.
20
+ pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
21
+
22
+ # Specifies the number of `workers` to boot in clustered mode.
23
+ # Workers are forked web server processes. If using threads and workers together
24
+ # the concurrency of the application would be max `threads` * `workers`.
25
+ # Workers do not work on JRuby or Windows (both of which do not support
26
+ # processes).
27
+ #
28
+ # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
29
+
30
+ # Use the `preload_app!` method when specifying a `workers` number.
31
+ # This directive tells Puma to first boot the application and load code
32
+ # before forking the application. This takes advantage of Copy On Write
33
+ # process behavior so workers use less memory.
34
+ #
35
+ # preload_app!
@@ -1,11 +1,15 @@
1
- require 'rack'
2
-
3
1
  module Jeanine
4
2
  class Mimes
5
3
  MimeTypeNotFound = Class.new(StandardError)
6
4
  MIME_TYPES_INVERTED = ::Rack::Mime::MIME_TYPES.invert
7
5
 
6
+ def self.loaded?
7
+ @loaded
8
+ end
9
+
8
10
  def self.load!
11
+ return if loaded?
12
+ @loaded = true
9
13
  register(:json, Rack::Mime::MIME_TYPES[".json"])
10
14
  register(:html, Rack::Mime::MIME_TYPES[".html"])
11
15
  register(:text, Rack::Mime::MIME_TYPES[".text"])
@@ -1,6 +1,15 @@
1
1
  require 'jeanine/view'
2
+ require 'jeanine/view_paths'
2
3
 
3
4
  module Jeanine
5
+ def self.view_paths
6
+ @_view_paths ||= Set.new(["views"])
7
+ end
8
+
9
+ def self.tilt_cache
10
+ @title_cache ||= Tilt::Cache.new
11
+ end
12
+
4
13
  class Renderer
5
14
  def self._renderers
6
15
  @_renderers ||= Set.new
@@ -139,4 +148,21 @@ module Jeanine
139
148
  text
140
149
  end
141
150
  end
151
+
152
+ module Rendering
153
+ def self.included(klass)
154
+ klass.extend ClassMethods
155
+ end
156
+
157
+ def render(*args)
158
+ @response.action_variables = instance_variables_cache
159
+ Renderer.new(@response).render(*args)
160
+ end
161
+
162
+ module ClassMethods
163
+ def append_view_path(path)
164
+ Jeanine.view_paths << path
165
+ end
166
+ end
167
+ end
142
168
  end
@@ -1,5 +1,4 @@
1
1
  require 'rack/request'
2
- require 'jeanine/headers'
3
2
 
4
3
  module Jeanine
5
4
  class Request < Rack::Request
@@ -17,8 +16,8 @@ module Jeanine
17
16
  super
18
17
  end
19
18
 
20
- def headers
21
- @headers ||= Jeanine::Headers.new(self)
19
+ def params
20
+ super.deep_transform_keys!(&:to_sym)
22
21
  end
23
22
 
24
23
  def post?
@@ -0,0 +1,41 @@
1
+ module Jeanine
2
+ module Rescuable
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.prepend InstanceMethods
6
+ end
7
+
8
+ module InstanceMethods
9
+ def call(env)
10
+ begin
11
+ super
12
+ rescue => error
13
+ handler = self.class.rescue_handlers[error.class.to_s]
14
+ raise error unless handler
15
+ if handler.is_a?(Symbol)
16
+ @response.write(send(handler, error))
17
+ else
18
+ @response.write(instance_exec(error, &handler))
19
+ end
20
+ @response.complete!
21
+ end
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ def rescue_from(*exceptions, with: nil, &block)
27
+ exceptions.each do |exception|
28
+ if with
29
+ rescue_handlers[exception.to_s] = with
30
+ else
31
+ rescue_handlers[exception.to_s] = block
32
+ end
33
+ end
34
+ end
35
+
36
+ def rescue_handlers
37
+ @rescue_handlers ||= {}
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,18 +2,13 @@ module Jeanine
2
2
  module Routing
3
3
  module Evaluation
4
4
  def route_eval
5
- before_find_route!
6
5
  route = find_route
7
-
8
6
  if route
9
- before_evaluate_route!
10
7
  result = instance_eval(&route[:block])
11
8
  @response.write(result)
12
- after_evaluate_route!
13
9
  else
14
10
  @response.status = 404
15
11
  end
16
- after_response!
17
12
  @response.complete!
18
13
  end
19
14
 
@@ -42,54 +37,6 @@ module Jeanine
42
37
  route
43
38
  end
44
39
 
45
- def before_find_route!
46
- run_before_callbacks!(:before_all)
47
- end
48
-
49
- def before_evaluate_route!
50
- run_before_callbacks!(:before)
51
- end
52
-
53
- def after_evaluate_route!
54
- run_after_callbacks!(:after)
55
- end
56
-
57
- def after_response!
58
- run_after_callbacks!(:after_all)
59
- end
60
-
61
- def run_before_callbacks!(type)
62
- if type == :before_all
63
- self.class._callbacks[type].each { |callback| eval_callback(&callback[:block]) }
64
- else
65
- matching_callbacks(type) do |callback|
66
- eval_callback(&callback[:block])
67
- end
68
- end
69
- end
70
-
71
- def run_after_callbacks!(type)
72
- if type == :after_all
73
- self.class._callbacks[type].each { |callback| eval_callback(&callback[:block]) }
74
- else
75
- matching_callbacks(type) do |callback|
76
- eval_callback(&callback[:block])
77
- end
78
- end
79
- end
80
-
81
- def matching_callbacks(type)
82
- self.class._callbacks[type].select do |callback|
83
- paths = callback[:paths]
84
- if paths.detect { |path| path.match?(@request.path_info) }
85
- yield callback
86
- end
87
- end
88
- end
89
-
90
- def eval_callback(*args, &callback)
91
- instance_exec(*args, &callback)
92
- end
93
40
  end
94
41
  end
95
42
  end
@@ -1,3 +1,3 @@
1
1
  module Jeanine
2
- VERSION = "0.4.0"
2
+ VERSION = "0.7.2"
3
3
  end
@@ -1,7 +1,8 @@
1
+ require 'tilt'
2
+
1
3
  module Jeanine
4
+
2
5
  module ViewPaths
3
- def append_view_path(path)
4
- Jeanine.view_paths << path
5
- end
6
+
6
7
  end
7
8
  end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jeanine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Brody
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2020-07-08 00:00:00.000000000 Z
12
12
  dependencies:
@@ -94,28 +94,52 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: A framework.
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A lightning-fast, batteries-included Ruby web micro-framework.
98
112
  email:
99
113
  - git@josh.mn
100
114
  executables: []
101
115
  extensions: []
102
116
  extra_rdoc_files: []
103
117
  files:
118
+ - README.md
119
+ - exe/jeanine
104
120
  - lib/jeanine.rb
105
121
  - lib/jeanine/app.rb
106
122
  - lib/jeanine/callbacks.rb
123
+ - lib/jeanine/cli.rb
107
124
  - lib/jeanine/core_ext.rb
108
125
  - lib/jeanine/core_ext/array.rb
109
126
  - lib/jeanine/core_ext/hash.rb
110
127
  - lib/jeanine/core_ext/nil_class.rb
111
128
  - lib/jeanine/core_ext/string.rb
112
129
  - lib/jeanine/environment.rb
130
+ - lib/jeanine/generator/new/Gemfile.tt
131
+ - lib/jeanine/generator/new/README.md.tt
132
+ - lib/jeanine/generator/new/app.rb.tt
133
+ - lib/jeanine/generator/new/config.ru.tt
134
+ - lib/jeanine/generator/new/config/boot.rb.tt
135
+ - lib/jeanine/generator/new/config/environment.rb.tt
136
+ - lib/jeanine/generator/new/config/puma.rb.tt
113
137
  - lib/jeanine/headers.rb
114
138
  - lib/jeanine/mimes.rb
115
139
  - lib/jeanine/path_proxy.rb
116
- - lib/jeanine/renderer.rb
140
+ - lib/jeanine/rendering.rb
117
141
  - lib/jeanine/request.rb
118
- - lib/jeanine/rescuing.rb
142
+ - lib/jeanine/rescuable.rb
119
143
  - lib/jeanine/response.rb
120
144
  - lib/jeanine/router.rb
121
145
  - lib/jeanine/routing.rb
@@ -147,8 +171,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
171
  - !ruby/object:Gem::Version
148
172
  version: '0'
149
173
  requirements: []
150
- rubygems_version: 3.0.3
174
+ rubyforge_project:
175
+ rubygems_version: 2.6.14.3
151
176
  signing_key:
152
177
  specification_version: 4
153
- summary: A framework.
178
+ summary: A lightning-fast, batteries-included Ruby web micro-framework.
154
179
  test_files: []
@@ -1,17 +0,0 @@
1
- module Jeanine
2
- module Rescuing
3
- def rescue_from(*exceptions, with: nil, &block)
4
- exceptions.each do |exception|
5
- if with
6
- rescue_handlers[exception] = with
7
- else
8
- rescue_handlers[exception] = block
9
- end
10
- end
11
- end
12
-
13
- def rescue_handlers
14
- @rescue_handlers ||= {}
15
- end
16
- end
17
- end