pretzel 0.1.3 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e05d6a69c72f4ba45c60b408450e799144a9e56e
4
- data.tar.gz: ec51b8960b12bd6c0e4b8dc2d20057551089ef09
3
+ metadata.gz: eda1d2b5c8b88a860d1881278ca7782a5a739cb6
4
+ data.tar.gz: 1f23c29e34fbae8f463a528e4a311dcfadd8f0cb
5
5
  SHA512:
6
- metadata.gz: a5efb05569eaa7bb78ac28685768106aa5e88280c8ad017ea49a06ea756c36119eed674390c096056abdf4a16ef9d1344be52c696ea4b005ffc5941cf29b0637
7
- data.tar.gz: 533058ca02af687c4ddbe22e4464cec7a16ccb0d226e2730cc03e8a856a5929fbc7ccffc6c17ab0022944ba71fb4cdeca394cf5ca5d3c58195017eea147afa96
6
+ metadata.gz: db7f4114905d34429e9a41efb623963a71b915293baef73a3e866f6e4d5eb441e2bb8f5f4b7d1f2409ccde6fed9695d1fdc88e09d476fd10a0e05a7620ab15a2
7
+ data.tar.gz: 45fd5052b6c18e97ba811823afe2dbb9f086996fb01a6975786993a14ebf437dd87bd43b72167f1c409c87f93fe8b6a24c9d9165d05863eb1b3a1f24aaefb7db
data/README.md CHANGED
@@ -1,7 +1,33 @@
1
+ ## The Pretzel suite
1
2
 
2
- # pretzel
3
- ![TravisCI badge](https://travis-ci.org/pretzelhands/pretzel.svg?branch=master)
4
- ![Version badge](https://badge.fury.io/rb/pretzel.svg)
3
+ [![TravisCI badge](https://travis-ci.org/pretzelhands/pretzel.svg?branch=master)](https://travis-ci.org/pretzelhands/pretzel)
4
+ [![Version badge](https://badge.fury.io/rb/pretzel.svg)](https://badge.fury.io/rb/pretzel)
5
5
  [![Code Climate](https://codeclimate.com/github/pretzelhands/pretzel/badges/gpa.svg)](https://codeclimate.com/github/pretzelhands/pretzel)
6
6
 
7
- ReadMe coming soon.
7
+ ---
8
+
9
+ Welcome to the canonical repo of the Pretzel suite, a tiny web framework inspired by the ideas of Sinatra and Nancy. This framework has some strong opinions on how to structure an application and thus may not be suited for everyone.
10
+
11
+ If you like convention-over-configuration and building web applications from small building blocks along the lines of the UNIX philosophy, you have come to the right place.
12
+
13
+ ### Philosophy
14
+
15
+ The Pretzel suite is built upon the UNIX philosopy. A piece of software should do one thing and do it well. The Pretzel core itself is a tiny 144 lines in 3 modules. It basically only provides routing, filters and it exposes some Rack middleware.
16
+
17
+ After that everything is an extension. Even the templating and the status/redirect/session methods. The goal is to create a framework which you can take and stick together the way you need it.
18
+
19
+ ### Documentation
20
+
21
+ The documentation is available in the `docs` folder. It is sorted by a xx-yy-name pattern, where xx is a major and yy a minor chapter. The documentation takes the approach to teach by example, thus you will get lots of code snippets to visualize how things work.
22
+
23
+ ### Bug reports
24
+
25
+ If you found a bug, feel free to send it in via the issue tracker on the right side. Or, if you know some code, maybe write a patch for it yourself! I usually lint my code with `ruby -wc`, and I'd ask you to do the same. Also don't forget to *write and run* tests. Otherwise I may go on neverending rants and we both don't want that.
26
+
27
+ ### Who's responsible for this and why?
28
+
29
+ The dude behind all of this is me, [Richard Blechinger.](http://twitter.com/F0lis) On the internet I'm more commonly known by nicknames "Folis" and "Pretzelhands" (See where the framework name comes from?). I'm a web developer who tries to learn as many things as humanly possible. This is why the Pretzel suite exists, too. It started as endeavour to look at Rack and how it works.
30
+
31
+ ### Licensing
32
+
33
+ MIT everytime all the time. Go ahead and do what you want.
@@ -0,0 +1,106 @@
1
+ # Basic Pretzel Application
2
+
3
+ The Pretzel suite comes with a very small core consisting of about 144 lines split
4
+ into 3 modules: Core, Routing::Evaluation and Routing::Methods. Every Pretzel application
5
+ also automatically includes the Extension::Convenience module which provides some
6
+ neat wrappers around common functionality.
7
+
8
+ ## Directory structure
9
+
10
+ Before we get down and dirty with the code, let's talk management. The Pretzel suite
11
+ has strong opinions on where things should go. The basic folder structure for a Pretzel
12
+ application looks like this:
13
+
14
+ ```
15
+ my_app
16
+ |
17
+ |- config.ru
18
+ |- application.rb
19
+ |- assets
20
+ |- views
21
+ |- includes
22
+
23
+ ```
24
+
25
+ `config.ru` is your rackup file. You can read more about that down below. The `application.rb`
26
+ file can be named whatever you want, and it should contain the class declaration
27
+ your application.
28
+
29
+ The `assets` directory is a folder for your static content. CSS/JS, images, etc.
30
+ Everything is mapped 1-to-1 in the URL scheme, so if you put a file under `/assets/css/style.css`
31
+ you will find it under `/assets/css/style.css` when the application is running.
32
+
33
+ The `views` folder is where your `liquid` templates go. (See 03-00-templating for more
34
+ information). The `includes` folder inside contains the `liquid` partials.
35
+
36
+ **NOTE:** These settings are fixed and may not be changed at runtime. Convention over
37
+ configuration takes effect here.
38
+
39
+ ## Creating an application
40
+
41
+ A basic Pretzel application consists of a class inheriting from the Pretzel::Core
42
+ class. It looks like this:
43
+
44
+ ```ruby
45
+ require "pretzel/core"
46
+
47
+ class Application < Pretzel::Core
48
+ end
49
+ ```
50
+
51
+ This gives you the following functionality:
52
+
53
+ * Routing with 6 methods (`GET, POST, PUT, DELETE, OPTIONS, HEAD`)
54
+ * Before and after filters
55
+ * Access to a `Rack::Response` and `Rack::Request` module
56
+ * Ability to include Rack middleware with the `use` function
57
+ * A fully setup session hash, which can be accessed with `session`
58
+ * Wrapper functions for setting the response status and redirecting
59
+
60
+ ## Running your application
61
+
62
+ For running your application you have two options: Run it from the file directly
63
+ or run it with `rackup`. The Pretzel suite comes with Thin as web server, so you're
64
+ good to go.
65
+
66
+ ### Running the application directly
67
+
68
+ To run your application directly, you need to call one of the Rack handlers like this:
69
+
70
+ ```ruby
71
+ require "rack"
72
+ require "pretzel/core"
73
+
74
+ class Application < Pretzel::Core
75
+ end
76
+
77
+ Rack::Handler::Thin.run Application.new
78
+ ```
79
+
80
+ Then you can just run the following command from the terminal: `$ ruby application.rb`
81
+ and your application should be up and running!
82
+
83
+ ### Running the application via rackup
84
+
85
+ Running your application via `rackup` is a lot more flexible and is the recommended
86
+ way to get your things online. First setup your application in a file `application.rb`.
87
+
88
+ ```ruby
89
+ require "pretzel/core"
90
+
91
+ class Application < Pretzel::Core
92
+ end
93
+ ```
94
+
95
+ Then create a new file called `config.ru`, require your application and call the
96
+ `run` function. It looks like this:
97
+
98
+ ```ruby
99
+ require_relative "application"
100
+ run Application.new
101
+ ```
102
+
103
+ Finally execute this command in the directory of your `config.ru`: `$ rackup -o "0.0.0.0" -p PORT`
104
+
105
+ The port is freely configurable, but don't forget the `-o "0.0.0.0"` part as to listen
106
+ on all available interfaces.
@@ -0,0 +1,67 @@
1
+ ## Routing
2
+
3
+ Routing with the Pretzel suite is very close to Sinatra, with one exception:
4
+ The recommendation is not to do your routing in the class declaration, but outside of it.
5
+
6
+ It looks like this:
7
+
8
+ ```ruby
9
+ require "pretzel/core"
10
+
11
+ class Application < Pretzel::Core
12
+ end
13
+
14
+ Application.get "/" do
15
+ "Hello, World"
16
+ end
17
+ ```
18
+
19
+ This has the advantage, that you can split your routes into seperate files to keep
20
+ your application maintainable.
21
+
22
+ All routes are matched in order from first-declared to last-declared
23
+
24
+ ### Routing methods and blocks
25
+
26
+ There are 6 routing methods available to every Pretzel applications. They are as
27
+ follows: `get, post, put, delete, options, head`. Usually, if you're not deep down
28
+ into the HTTP spec, you will probably only need the first four.
29
+
30
+ Each routing method takes a route and a block as arguments. Routes can be declared
31
+ and visited with or without a trailing slash. The suite makes no differentiation
32
+ here for simplicity purposes.[1]
33
+
34
+ ```ruby
35
+ Application.get "/test" do
36
+ # Do stuff
37
+ end
38
+ ```
39
+
40
+ ### Block variables
41
+
42
+ Within blocks you have access to various variables that allow you
43
+ to easily modify and manipulate the data flowing around. The following objects
44
+ are available:
45
+
46
+ * request - A Rack::Request
47
+ * response - A Rack::Response
48
+ * parameters - A Hash containing the GET, POST and URL parameters of this route.
49
+
50
+ This follows the approach of not hiding anything from you and giving you full access
51
+
52
+ ### Named parameters
53
+
54
+ Each route can have named parameters in the URL, by prefixing the part with a
55
+ colon like this: `/hello/:name`. These parameters will be added to your parameters
56
+ hash in the route block
57
+
58
+ ```ruby
59
+ # Assume we access /hello/world in our browser
60
+ Application.get "/hello/:name" do
61
+ "Hello, #{parameters['name']}!" # => "Hello, world!"
62
+ end
63
+ ```
64
+
65
+ ----
66
+
67
+ [1] This actually made the route parsing regex more complicated, but whatever.
@@ -0,0 +1,25 @@
1
+ ## Filters
2
+
3
+ Filters are functions that can handle things for you whenever a route is called
4
+ The Pretzel suite has two seperate filters: `before` and `after`.
5
+
6
+ They are declared very similar to routes:
7
+
8
+ ```ruby
9
+ Application.before do
10
+ # Do this before every route
11
+ end
12
+
13
+ Application.after do
14
+ # Do this after every route
15
+ end
16
+ ```
17
+
18
+ Those filters are executed before and after each call to a route. In the
19
+ function blocks you have access to two objects:
20
+
21
+ * response - A Rack::Response
22
+ * request - A Rack::Request
23
+
24
+ Thus these filters can be used to modify headers, request data and such as you
25
+ see fit. Quite handy!
@@ -0,0 +1,36 @@
1
+ ## Mapping
2
+
3
+ Mapping is one of the most awesome features of Rack applications.
4
+ It allows you to put together a bunch of seperate applications into a single one,
5
+ thus allowing you to create service architectures.
6
+
7
+ Let's see how it works:
8
+
9
+ ```ruby
10
+ require "pretzel/core"
11
+
12
+ class Application < Pretzel::Core
13
+ end
14
+
15
+ class SubApplication < Pretzel::Core
16
+ end
17
+
18
+ SubApplication.get "/test" do
19
+ "Hello, SubApplication"
20
+ end
21
+
22
+ Application.get "/" do
23
+ "Hello, MainApplication"
24
+ end
25
+
26
+ Application.map "/sub" do
27
+ run SubApplication.new
28
+ end
29
+ ```
30
+
31
+ Now in this setup whenever you access a route that's on the `/sub` route, you will
32
+ get forwarded to the routes of the `SupApplication`.
33
+
34
+ Thus when you access `/sub/test` you will get the response `Hello, SubApplication`
35
+ If you use this efficiently you can build an application on the so-called service
36
+ architecture, which is pretty neat!
@@ -0,0 +1,45 @@
1
+ ## Convenience methods
2
+
3
+ The Pretzel suite comes with a set of three convenience methods. These are not part of
4
+ the Core framework, but are still included with every Pretzel project via the ways
5
+ of Pretzel::Core.
6
+
7
+ The convenience methods are defined in `Pretzel::Extension::Convenience` and the following
8
+ are available:
9
+
10
+ * redirect
11
+ * session
12
+ * status
13
+
14
+ **NOTE:** All convenience functions are only available in the *route blocks.*
15
+
16
+ ### redirect(url)
17
+
18
+ The `redirect` function allows you to easily execute a HTTP redirect to another URL
19
+ of your application. It only takes a single argument and is called like this:
20
+
21
+ ```ruby
22
+ redirect "/redirect-page"
23
+ ```
24
+
25
+ ### session
26
+
27
+ The `session` method is probably the most useful of the convenience functions. It
28
+ does what it says on the tin: Handle a session. It's already all setup with signed
29
+ cookies by the Pretzel::Core, so you can use it right away. It can be interacted
30
+ with as a regular Hash. It's just a thin wrapper around `request.session`.
31
+
32
+ ```ruby
33
+ session[:my_var] = "Hello, World" # Set a session variable
34
+ session[:my_var] # => "Hello, World"
35
+ ```
36
+
37
+ ### status(status)
38
+
39
+ `status` is a simple wrapper around response.status that allows you to set the HTTP
40
+ status of your response. This is usually done with APIs to indicate various success
41
+ and error states. `status` takes a single argument
42
+
43
+ ```ruby
44
+ status 201 # Set the status to "Resource created"
45
+ ```
@@ -0,0 +1,35 @@
1
+ ## JSON
2
+
3
+ The Pretzel suite comes with a predelivered JSON extension (`Pretzel::Extension::JSON`)
4
+ that helps you easily send JSON responses for an API or something similar. It is a non-core
5
+ extension and you have to manually add it to your application.
6
+
7
+ You can include it like this:
8
+
9
+ ```ruby
10
+ require "pretzel/core"
11
+ require "pretzel/ext/json"
12
+
13
+ class Application < Pretzel::Core
14
+ extends Pretzel::Extension::JSON
15
+ end
16
+ ```
17
+
18
+ And you're ready to go! The JSON module only provides a single method: `json`.
19
+ You can call this method with two parameters: A Hash and a `status`.
20
+
21
+ Only the hash is required. If you do not set a status, the response will just return
22
+ the status `200 OK`.
23
+
24
+ Calling it looks like this:
25
+
26
+ ```ruby
27
+ Application.get "/json" do
28
+ json({
29
+ :hello => "world"
30
+ }, 201)
31
+ end
32
+ ```
33
+
34
+ This sets the response status to 201, the content type to "application/json" and
35
+ converts the Hash to JSON according to the specification.
@@ -0,0 +1,123 @@
1
+ ## Templating
2
+
3
+ Another pre-delivered feature of the Pretzel suite is templating. This is done
4
+ with the excellent [Liquid templating language.](https://github.com/shopify/liquid)
5
+
6
+ The purpose of this document is to show how to use the Pretzel suite with Liquid,
7
+ not to explain the templating language itself. For that, visit the link above and
8
+ look through the wiki to get a basic grasp.
9
+
10
+ Pretzel projects once again take a convention-over-configuration approach to templating.
11
+ All your templates must be stored in a `views` that resides next to your application file.
12
+
13
+ Inside the view folder you have free reign as to how to structure your templates with
14
+ one notable exceptions: *Liquid partials go in the `views/includes` folder*. As a fair
15
+ hint: Remember that all partials need to be named with an underscore in front. This
16
+ has caused me some headaches before.
17
+
18
+ Now for the folder structure:
19
+
20
+ ```
21
+ app
22
+ |
23
+ |- application.rb
24
+ |- config.ru
25
+ |- views
26
+ |- includes
27
+ |- _partial.liquid
28
+ |- your_template.liquid
29
+ ```
30
+
31
+ ### Preparing your application
32
+
33
+ The code side of things is even simpler. The templating functionality is provided
34
+ in an extension: `Pretzel::Extension::Templating`. As with other extensions you have
35
+ to include it before using it, like so:
36
+
37
+ ```ruby
38
+ require "pretzel/core"
39
+ require "pretzel/ext/templating"
40
+
41
+ class Application < Pretzel::Core
42
+ extends Pretzel::Extension::Templating
43
+ end
44
+ ```
45
+
46
+ ### Using basic templates
47
+
48
+ The extension exposes a single function: `render`, which is used like this:
49
+
50
+ ```ruby
51
+ Application.get "/" do
52
+ render :index
53
+ end
54
+ ```
55
+
56
+ The template name is passed as first argument. It can be either a symbol or a string.
57
+ It *must* not contain the file extension and is always rooted in the views folder.
58
+
59
+ Here are some more examples
60
+
61
+ ```ruby
62
+ render :index # => views/index.liquid
63
+ render "subfolder/my_template" # => views/subfolder/my_template.liquid
64
+ render :"subfolder/other_template" # => views/subfolder/other_template.liquid
65
+ ```
66
+
67
+ ### Templates and locals
68
+
69
+ Most templates aren't satisfied with simple rendering, and usually you want to pass
70
+ a bunch of variables (so called `locals`) in. The render function has that covered:
71
+
72
+ ```ruby
73
+ Application.get "/" do
74
+ render :index, {
75
+ "name" => "Richard"
76
+ }
77
+ end
78
+ ```
79
+
80
+ The locals are always passed in as a simple Ruby Hash. For more information on locals,
81
+ see the Liquid documentation!
82
+
83
+ ### Layouts
84
+
85
+ Many applications have some sort of HTML structure that they want to persist across
86
+ various views. This is usually called a layout or a theme. The Pretzel suite has
87
+ this integrated too.
88
+
89
+ Whenever you call `render` on a template, the framework will look for a file in your
90
+ `views` folder called `layout.liquid`. This template exposes a special variable
91
+ called `template`. An example layout may look like this:
92
+
93
+ ```html
94
+ <!DOCTYPE html>
95
+ <html lang="en">
96
+ <head>
97
+ <meta charset="UTF-8">
98
+ <title>Document</title>
99
+ </head>
100
+ <body>
101
+ {{ template }}
102
+ </body>
103
+ </html>
104
+ ```
105
+
106
+ The part where you output template is, shockingly, the place where your template will
107
+ appear. Cool, huh?
108
+
109
+ #### Deactivating the layout
110
+
111
+ If there is no `layout.liquid` file, the Pretzel suite will just not apply a layout.
112
+ In case you have created a layout but you want to deactivate it for a certain route,
113
+ you just need to pass `"layout" => false` into the locals like so:
114
+
115
+ ```ruby
116
+ Application.get "/no-layout" do
117
+ render :some_template, {
118
+ "layout" => false
119
+ }
120
+ end
121
+ ```
122
+
123
+ This will supress the layout rendering for this template.
@@ -0,0 +1,17 @@
1
+ ## Rack middleware
2
+
3
+ Since Pretzel applications are just Rack applications under the hood you
4
+ can extend them with any type of Rack middleware. It's really easy, too.
5
+
6
+ Here's how it is done:
7
+
8
+ ```ruby
9
+ require "pretzel/core"
10
+ require "rack/lobster" # The middleware
11
+
12
+ class Application < Pretzel::Core
13
+ use Rack::Lobster
14
+ end
15
+ ```
16
+
17
+ And done.
@@ -0,0 +1,117 @@
1
+ ## Pretzel extensions
2
+
3
+ While Rack middleware is great for low-level extensions, sometimes you
4
+ may want to extend the Pretzel suite on a somewhat higher level.
5
+
6
+ Maybe your extension requires some custom routes or you want to include
7
+ some Liquid extensions? This is the reason for the `extends` method.
8
+
9
+ It is used like this:
10
+
11
+ ```ruby
12
+ require "pretzel/core"
13
+
14
+ class Application < Pretzel::Core
15
+ extends Pretzel::Extension::Test
16
+ end
17
+ ```
18
+
19
+ And you're good to go.
20
+
21
+ ## Structure
22
+
23
+ Each extension consists of two parts: `App` and `Route`.
24
+ Both are submodules of your extension. The structure looks like this.
25
+
26
+ ```ruby
27
+ module Pretzel::Extension
28
+
29
+ module Test
30
+ module App
31
+ # Code-y awesomeness
32
+ end
33
+
34
+ module Route
35
+ # Code-y awesomeness
36
+ end
37
+ end
38
+
39
+ end
40
+ ```
41
+
42
+ ## Where to declare things
43
+
44
+ The `App` and `Route` modules are rather aptly named. Any methods declared in
45
+ the `App` module will be available in the class declaration like this:
46
+
47
+ ```ruby
48
+ class Application < Pretzel::Core
49
+ extends Your::Extension
50
+ your_method
51
+ end
52
+ ```
53
+
54
+ On the other side, any methods declared in the `Route` module are available in
55
+ the route controllers like this:
56
+
57
+ ```ruby
58
+ class Application < Pretzel::Core
59
+ extends Your::Extension
60
+ end
61
+
62
+ Application.get "/" do
63
+ your_extension
64
+ end
65
+ ```
66
+
67
+ ### Custom extension routes
68
+
69
+ The `Route` module is also where you want to declare your custom routes.
70
+ This can be done by using Ruby's `self.included` method to your advantage:
71
+
72
+ ```ruby
73
+ module Pretzel::Extension
74
+
75
+ module Test
76
+ module Route
77
+
78
+ def self.included(application)
79
+ application.get "/ext/index" do
80
+ "Extensions!"
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+ end
88
+ ```
89
+
90
+ ### Extending Liquid
91
+
92
+ If you want to keep your application clean and modular, you can also use the
93
+ `Route` module to extend Liquid. You can read all about [the subject matter here.](https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#extending-liquid)
94
+
95
+ An example Liquid extension may look like this:
96
+
97
+ ```ruby
98
+
99
+ module Pretzel::Extension
100
+
101
+ module Test
102
+ module Route
103
+ module TestFilter
104
+ def reverse(string)
105
+ string.reverse!
106
+ end
107
+ end
108
+
109
+ Liquid::Template.register_filter(TestFilter)
110
+ end
111
+ end
112
+
113
+ end
114
+ ```
115
+
116
+ It can then be included in your application with `extends` and you're ready
117
+ to use the filter in your templates. (Of course you can also create blocks and tags.)
data/lib/pretzel/core.rb CHANGED
@@ -3,17 +3,21 @@ require "forwardable"
3
3
  require "securerandom"
4
4
 
5
5
  require_relative "version"
6
+ require_relative "extends"
7
+
6
8
  require_relative "ext/convenience"
7
9
 
8
10
  require_relative "routing/eval"
9
11
  require_relative "routing/methods"
10
12
 
13
+
11
14
  module Pretzel
12
15
  class Core
16
+ extend Pretzel::Extension
13
17
  include Pretzel::Routing::Evaluation
14
18
  extend Pretzel::Routing::Methods
15
19
 
16
- include Pretzel::Extension::Convenience
20
+ extends Pretzel::Extension::Convenience
17
21
 
18
22
  attr_reader :request, :response, :parameters
19
23
 
@@ -2,16 +2,18 @@ module Pretzel
2
2
  module Extension
3
3
  module Convenience
4
4
 
5
- def status(status)
6
- response.status = status
7
- end
5
+ module Route
6
+ def status(status)
7
+ response.status = status
8
+ end
8
9
 
9
- def session
10
- request.session || raise("Rack::Session not set.")
11
- end
10
+ def session
11
+ request.session || raise("Rack::Session not set.")
12
+ end
12
13
 
13
- def redirect(url)
14
- response.redirect url
14
+ def redirect(url)
15
+ response.redirect url
16
+ end
15
17
  end
16
18
 
17
19
  end
@@ -4,11 +4,13 @@ module Pretzel
4
4
  module Extension
5
5
  module JSON
6
6
 
7
- def json(hash, status=200)
8
- response["Content-Type"] = "application/json"
9
- response.status = status
7
+ module Route
8
+ def json(hash, status=200)
9
+ response["Content-Type"] = "application/json"
10
+ response.status = status
10
11
 
11
- hash.to_json
12
+ hash.to_json
13
+ end
12
14
  end
13
15
 
14
16
  end
@@ -3,29 +3,33 @@ require "liquid"
3
3
  module Pretzel
4
4
  module Extension
5
5
  module Templating
6
- def self.included(_class)
7
- Liquid::Template.file_system = Liquid::LocalFileSystem.new("#{Dir.pwd}/views/includes")
8
- end
9
6
 
10
- def render(path, locals = {})
11
- response["Content-Type"] = "text/html"
12
- layout_file = File.expand_path("#{Dir.pwd}/views/layout.liquid")
13
- raw_file = File.expand_path("#{Dir.pwd}/views/#{path.to_s}.liquid")
14
-
15
- template = Liquid::Template.parse(File.read(raw_file))
7
+ module Route
8
+ def self.included(_class)
9
+ Liquid::Template.file_system = Liquid::LocalFileSystem.new("#{Dir.pwd}/views/includes")
10
+ end
11
+
12
+ def render(path, locals = {})
13
+ response["Content-Type"] = "text/html"
14
+ layout_file = File.expand_path("#{Dir.pwd}/views/layout.liquid")
15
+ raw_file = File.expand_path("#{Dir.pwd}/views/#{path.to_s}.liquid")
16
+
17
+ template = Liquid::Template.parse(File.read(raw_file))
16
18
 
17
- if File.exist?(layout_file)
18
- # Always render the layout, unless explicitly told otherwise.
19
- unless locals["layout"] == false
20
- layout = Liquid::Template.parse(File.read(layout_file))
21
- layout.render({ "template" => template.render(locals) })
19
+ if File.exist?(layout_file)
20
+ # Always render the layout, unless explicitly told otherwise.
21
+ unless locals["layout"] == false
22
+ layout = Liquid::Template.parse(File.read(layout_file))
23
+ layout.render({ "template" => template.render(locals) })
24
+ else
25
+ template.render(locals)
26
+ end
22
27
  else
23
28
  template.render(locals)
24
29
  end
25
- else
26
- template.render(locals)
27
30
  end
28
31
  end
32
+
29
33
  end # end module
30
34
  end # end module
31
35
  end # end module
@@ -0,0 +1,15 @@
1
+ module Pretzel
2
+ module Extension
3
+
4
+ def extends(extension)
5
+ if extension.const_defined? :Route
6
+ include extension::Route
7
+ end
8
+
9
+ if extension.const_defined? :App
10
+ extend extension::App
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Pretzel
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/test/scrap.rb CHANGED
@@ -2,14 +2,16 @@
2
2
  # implemented. The code here is not intended to be sensible.
3
3
 
4
4
  require_relative "setup_environment"
5
+ require_relative "scrap_extension"
5
6
 
6
7
  class ScrapApplication < Pretzel::Core
7
- include Pretzel::Extension::Templating
8
- include Pretzel::Extension::JSON
8
+ extends Pretzel::Extension::Templating
9
+ extends Pretzel::Extension::Scrap
9
10
  end
10
11
 
11
12
  ScrapApplication.get "/" do
12
- json({ :hello => "world" }, 201)
13
+ some_class_stuff "classy test"
14
+ some_instance_stuff "Test!"
13
15
  end
14
16
 
15
17
  ScrapApplication.get "/yolo/" do
@@ -0,0 +1,39 @@
1
+
2
+
3
+ module Pretzel
4
+ module Extension
5
+
6
+ class Scrap
7
+ module Instance
8
+ def some_instance_stuff(text)
9
+ p text
10
+ end
11
+ end
12
+
13
+ module App
14
+ def some_class_stuff(text)
15
+ p "CLASS: #{text}"
16
+ end
17
+ end
18
+
19
+ module Routes
20
+ def self.included(app)
21
+ app.get "/ext/test" do
22
+ render :index
23
+ end
24
+ end
25
+ end
26
+
27
+ module Templates
28
+ module TestFilter
29
+ def tester(input)
30
+ input.reverse!
31
+ end
32
+ end
33
+
34
+ Liquid::Template.register_filter(TestFilter)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,61 @@
1
+ require_relative "setup_environment"
2
+
3
+ module Pretzel
4
+ module Extension
5
+ class Test
6
+ module Instance
7
+
8
+ end
9
+
10
+ module App
11
+ def class_method
12
+ "Class method"
13
+ end
14
+ end
15
+
16
+ module Route
17
+ def instance_method
18
+ "Instance method"
19
+ end
20
+
21
+ def self.included(app)
22
+ app.get "/ext/index" do
23
+ render :index
24
+ end
25
+
26
+ app.get "/ext/instance" do
27
+ instance_method
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+
36
+ class ExtensionApplication < Pretzel::Core
37
+ extends Pretzel::Extension::Templating
38
+ extends Pretzel::Extension::Test
39
+ end
40
+
41
+ class TestExtension < Minitest::Test
42
+ include Rack::Test::Methods
43
+
44
+ def app
45
+ ExtensionApplication.new
46
+ end
47
+
48
+ def test_extension_route
49
+ get "/ext/index"
50
+ assert last_response.body.include? "Hello, World!"
51
+ end
52
+
53
+ def test_extension_classmethod
54
+ assert_equal ExtensionApplication.class_method, "Class method"
55
+ end
56
+
57
+ def test_extension_instancemethod
58
+ get "/ext/instance"
59
+ assert_equal last_response.body, "Instance method"
60
+ end
61
+ end
data/test/test_json.rb CHANGED
@@ -2,7 +2,7 @@ require_relative "setup_environment"
2
2
  require "rack"
3
3
 
4
4
  class JSONApplication < Pretzel::Core
5
- include Pretzel::Extension::JSON
5
+ extends Pretzel::Extension::JSON
6
6
  end
7
7
 
8
8
  JSONApplication.get "/" do
@@ -2,7 +2,7 @@ require_relative "setup_environment"
2
2
  require "rack"
3
3
 
4
4
  class TemplatingApplication < Pretzel::Core
5
- include Pretzel::Extension::Templating
5
+ extends Pretzel::Extension::Templating
6
6
  end
7
7
 
8
8
  TemplatingApplication.get "/" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretzel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Blechinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-01 00:00:00.000000000 Z
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -94,18 +94,30 @@ files:
94
94
  - LICENSE
95
95
  - README.md
96
96
  - Rakefile
97
+ - docs/01-00-application.md
98
+ - docs/01-01-routing.md
99
+ - docs/01-02-filters.md
100
+ - docs/01-04-mapping.md
101
+ - docs/02-00-conveniece-methods.md
102
+ - docs/02-01-json.md
103
+ - docs/03-00-templating.md
104
+ - docs/04-01-middleware.md
105
+ - docs/04-02-extensions.md
97
106
  - lib/pretzel/core.rb
98
107
  - lib/pretzel/ext/convenience.rb
99
108
  - lib/pretzel/ext/json.rb
100
109
  - lib/pretzel/ext/templating.rb
110
+ - lib/pretzel/extends.rb
101
111
  - lib/pretzel/routing/eval.rb
102
112
  - lib/pretzel/routing/methods.rb
103
113
  - lib/pretzel/version.rb
104
114
  - pretzel.gemspec
105
115
  - test/assets/test.css
106
116
  - test/scrap.rb
117
+ - test/scrap_extension.rb
107
118
  - test/setup_environment.rb
108
119
  - test/test_convenience.rb
120
+ - test/test_extension.rb
109
121
  - test/test_filters.rb
110
122
  - test/test_json.rb
111
123
  - test/test_map.rb
@@ -145,8 +157,10 @@ summary: The Pretzel web application core
145
157
  test_files:
146
158
  - test/assets/test.css
147
159
  - test/scrap.rb
160
+ - test/scrap_extension.rb
148
161
  - test/setup_environment.rb
149
162
  - test/test_convenience.rb
163
+ - test/test_extension.rb
150
164
  - test/test_filters.rb
151
165
  - test/test_json.rb
152
166
  - test/test_map.rb