jeanine 0.1.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d88a21a82401395ddca515402a07e3155939eb0
4
- data.tar.gz: e6edce8a4097864466149cf6769765332a868c76
3
+ metadata.gz: 605777e016821bd0a6bd5e400d84dc6c5ad1e2fd
4
+ data.tar.gz: 5547bdb35a9a9612f6f1d327c3fc0fa14bae5f83
5
5
  SHA512:
6
- metadata.gz: 17f7d684adeefc7ec56e7244c6c53fddeafb9d037e4a1ee9aab94d8925193a39a95d0a079ba2aad85ae3f5a64b972315a7893f6ced6d07ba7e693923be9cc67e
7
- data.tar.gz: 82082d64a1620c947e51aa84d9ada5701825c0525061cd930022b8ef68611338570fc64f20038a4605e48bf1d27578c668ff2923a0ef7d88bc3b55435792877d
6
+ metadata.gz: e83f8c437da8c145fd618d425e8e1dcf6fb223b492daab6c0ddcb8c24cea734a3d6e0a529ea67713aff2148dd88e13de0f0d5f26f397d06fc66dca7cf6c86995
7
+ data.tar.gz: b87de6a104f9b2b7ebd09e10a53aee551dd81b5ea9bcbadd43af7a599e472aeb76b5bb927067c5e0f05cac64286e09387ceca0966c04a02b23429f0eea703c3e
@@ -1,15 +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.tilt_cache
12
- @title_cache ||= Tilt::Cache.new
10
+ def self._installed_plugins
11
+ @_installed_plugins ||= []
13
12
  end
14
13
 
15
14
  def self.logger
@@ -23,4 +22,7 @@ module Jeanine
23
22
  def self.router
24
23
  @router ||= Router.new
25
24
  end
25
+
26
+ autoload :Router, 'jeanine/router'
27
+ autoload :App, 'jeanine/app'
26
28
  end
@@ -1,17 +1,35 @@
1
- require 'jeanine/callbacks'
2
1
  require 'jeanine/mimes'
3
2
  require 'jeanine/request'
4
3
  require 'jeanine/response'
5
- require 'jeanine/renderer'
6
4
  require 'jeanine/routing'
7
5
 
8
6
  module Jeanine
9
7
  class App
10
8
  include Routing::Evaluation
9
+
11
10
  attr_reader :request, :response
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
+
12
31
  class << self
13
32
  include Routing::DSL
14
- include Callbacks
15
33
 
16
34
  alias :_new :new
17
35
  def new(*args, &block)
@@ -54,11 +72,6 @@ module Jeanine
54
72
  end
55
73
  end
56
74
 
57
- def render(*args)
58
- @response.action_variables = instance_variables_cache
59
- Renderer.new(@response).render(*args)
60
- end
61
-
62
75
  def instance_variables_cache
63
76
  instance_variables.each_with_object({}) do |var, obj|
64
77
  obj[var] = instance_variable_get(var)
@@ -1,28 +1,106 @@
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 _register_callback(type, paths = [], &block)
13
- if paths == []
14
- _callbacks["#{type}_all".to_sym] << { block: block }
15
- else
16
- _callbacks[type] << { paths: paths, block: block }
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)
17
20
  end
18
- end
19
21
 
20
- def before(*paths, &block)
21
- _register_callback(:before, paths, &block)
22
+ def after(*paths, &block)
23
+ _register_callback(:after, paths, &block)
24
+ end
25
+
26
+ private
27
+
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
22
35
  end
23
36
 
24
- def after(*paths, &block)
25
- _register_callback(:after, paths, &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)
103
+ end
26
104
  end
27
105
  end
28
106
  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
@@ -1,9 +1,15 @@
1
1
  module Jeanine
2
2
  class Mimes
3
3
  MimeTypeNotFound = Class.new(StandardError)
4
- MIME_TYPES_INVERTED = Rack::Mime::MIME_TYPES.invert
4
+ MIME_TYPES_INVERTED = ::Rack::Mime::MIME_TYPES.invert
5
+
6
+ def self.loaded?
7
+ @loaded
8
+ end
5
9
 
6
10
  def self.load!
11
+ return if loaded?
12
+ @loaded = true
7
13
  register(:json, Rack::Mime::MIME_TYPES[".json"])
8
14
  register(:html, Rack::Mime::MIME_TYPES[".html"])
9
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
@@ -81,6 +90,16 @@ module Jeanine
81
90
  Thread.current[:tilt_cache] ||= Tilt::Cache.new
82
91
  end
83
92
 
93
+ def find_template!(template)
94
+ Jeanine.view_paths.to_a.each do |path|
95
+ template_with_path = "#{path}/#{template}"
96
+ if File.exist?(template_with_path)
97
+ return template_with_path
98
+ end
99
+ end
100
+ raise "Template not found in view paths. Looking for #{template} in #{Jeanine.view_paths.to_a.join(', ')}"
101
+ end
102
+
84
103
  def html(engine, template_name, options = {}, locals = {}, &block)
85
104
  locals = options.delete(:locals) || locals || {}
86
105
  layout = options[:layout]
@@ -94,6 +113,7 @@ module Jeanine
94
113
  unless layout.include?("layouts/")
95
114
  layout = "layouts/#{layout}"
96
115
  end
116
+ layout = find_template!(layout)
97
117
  options = options.merge(layout: false, scope: scope)
98
118
  catch(:layout_missing) { return html(engine, layout, options, locals) { output } }
99
119
  end
@@ -104,7 +124,8 @@ module Jeanine
104
124
  Tilt::Cache.new.fetch engine, template_name, options do
105
125
  template = Tilt[engine]
106
126
  raise "Template engine not found: #{engine}" if template.nil?
107
- template.new("views/#{template_name}", options)
127
+ template_name = find_template!(template_name)
128
+ template.new(template_name, options)
108
129
  end
109
130
  end
110
131
 
@@ -127,4 +148,21 @@ module Jeanine
127
148
  text
128
149
  end
129
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
130
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
@@ -1,20 +1,14 @@
1
1
  module Jeanine
2
2
  module Routing
3
3
  module Evaluation
4
- IGNORED_INSTANCE_VARIABLES = [:@env]
5
4
  def route_eval
6
- before_find_route!
7
5
  route = find_route
8
-
9
6
  if route
10
- before_evaluate_route!
11
7
  result = instance_eval(&route[:block])
12
8
  @response.write(result)
13
- after_evaluate_route!
14
9
  else
15
10
  @response.status = 404
16
11
  end
17
- after_response!
18
12
  @response.complete!
19
13
  end
20
14
 
@@ -34,7 +28,7 @@ module Jeanine
34
28
  while index < matches.captures.size
35
29
  param = route[:params][index]
36
30
  @request.params[param] = matches.captures[index]
37
- if index == match.captures.size
31
+ if index == matches.captures.size
38
32
  @request.params[param].gsub!(@request.format)
39
33
  end
40
34
  index += 1
@@ -43,54 +37,6 @@ module Jeanine
43
37
  route
44
38
  end
45
39
 
46
- def before_find_route!
47
- run_before_callbacks!(:before_all)
48
- end
49
-
50
- def before_evaluate_route!
51
- run_before_callbacks!(:before)
52
- end
53
-
54
- def after_evaluate_route!
55
- run_after_callbacks!(:after)
56
- end
57
-
58
- def after_response!
59
- run_after_callbacks!(:after_all)
60
- end
61
-
62
- def run_before_callbacks!(type)
63
- if type == :before_all
64
- self.class._callbacks[type].each { |callback| eval_callback(&callback[:block]) }
65
- else
66
- matching_callbacks(type) do |callback|
67
- eval_callback(&callback[:block])
68
- end
69
- end
70
- end
71
-
72
- def run_after_callbacks!(type)
73
- if type == :after_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 matching_callbacks(type)
83
- self.class._callbacks[type].select do |callback|
84
- paths = callback[:paths]
85
- if paths.detect { |path| path.match?(@request.path_info) }
86
- yield callback
87
- end
88
- end
89
- end
90
-
91
- def eval_callback(*args, &callback)
92
- instance_exec(*args, &callback)
93
- end
94
40
  end
95
41
  end
96
42
  end
@@ -0,0 +1,7 @@
1
+ module Jeanine
2
+ module Session
3
+ def session
4
+ env['rack.session']
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module Jeanine
2
- VERSION = "0.1.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,8 @@
1
+ require 'tilt'
2
+
3
+ module Jeanine
4
+
5
+ module ViewPaths
6
+
7
+ end
8
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jeanine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Brody
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-07 00:00:00.000000000 Z
11
+ date: 2020-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -53,7 +53,49 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-reporters
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack-test
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
101
  - - ">="
@@ -85,15 +127,18 @@ files:
85
127
  - lib/jeanine/headers.rb
86
128
  - lib/jeanine/mimes.rb
87
129
  - lib/jeanine/path_proxy.rb
88
- - lib/jeanine/renderer.rb
130
+ - lib/jeanine/rendering.rb
89
131
  - lib/jeanine/request.rb
132
+ - lib/jeanine/rescuable.rb
90
133
  - lib/jeanine/response.rb
91
134
  - lib/jeanine/router.rb
92
135
  - lib/jeanine/routing.rb
93
136
  - lib/jeanine/routing/dsl.rb
94
137
  - lib/jeanine/routing/evaluation.rb
138
+ - lib/jeanine/session.rb
95
139
  - lib/jeanine/version.rb
96
140
  - lib/jeanine/view.rb
141
+ - lib/jeanine/view_paths.rb
97
142
  homepage: https://github.com/joshmn/jeanine
98
143
  licenses:
99
144
  - MIT