keynote 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of keynote might be problematic. Click here for more details.
- data/README.md +243 -5
- data/lib/keynote.rb +16 -1
- data/lib/keynote/controller.rb +3 -2
- data/lib/keynote/helper.rb +2 -2
- data/lib/keynote/presenter.rb +6 -2
- data/lib/keynote/rumble.rb +5 -5
- data/lib/keynote/version.rb +1 -1
- data/spec/helper.rb +2 -2
- data/spec/keynote_spec.rb +44 -25
- data/spec/railtie_spec.rb +4 -3
- data/spec/rumble_spec.rb +7 -7
- metadata +39 -45
data/README.md
CHANGED
@@ -1,8 +1,246 @@
|
|
1
|
-
|
1
|
+
# Keynote
|
2
2
|
|
3
|
-
|
3
|
+
*Flexible presenters for Rails.*
|
4
4
|
|
5
|
-
|
5
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/rf-/keynote)
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
A presenter is an object that encapsulates view logic. Like Rails helpers,
|
8
|
+
presenters help you keep complex logic out of your templates.
|
9
|
+
|
10
|
+
Keynote provides a consistent interface for defining and instantiating
|
11
|
+
presenters.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### The basic idea
|
16
|
+
|
17
|
+
A simple case is making a presenter that's named after a model class and holds
|
18
|
+
helper methods related to that model.
|
19
|
+
|
20
|
+
``` ruby
|
21
|
+
# app/presenters/user_presenter.rb
|
22
|
+
|
23
|
+
class UserPresenter < Keynote::Presenter
|
24
|
+
presents :user
|
25
|
+
|
26
|
+
def display_name
|
27
|
+
"#{user.first_name} #{user.last_name}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def profile_link
|
31
|
+
link_to user, display_name, data: {user_id: user.id}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
You can then instantiate it by calling the `present` method (aliased to `k`) in
|
37
|
+
a view, helper, controller, or another presenter.
|
38
|
+
|
39
|
+
``` erb
|
40
|
+
<%# app/layouts/_header.html.erb %>
|
41
|
+
|
42
|
+
<div id="header">
|
43
|
+
...
|
44
|
+
<div class="profile_link">
|
45
|
+
<%= k(current_user).profile_link %>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
```
|
49
|
+
|
50
|
+
If you pass anything other than a symbol as the first parameter of
|
51
|
+
`present`/`k`, Keynote will assume you want to instantiate a presenter named
|
52
|
+
after the class of that object -- in this case, the model is a `User`, so
|
53
|
+
Keynote looks for a class called `UserPresenter`.
|
54
|
+
|
55
|
+
### Generating HTML
|
56
|
+
|
57
|
+
To make it easier to generate slightly more complex chunks of HTML, Keynote
|
58
|
+
includes a modified version of Magnus Holm's [Rumble](https://github.com/judofyr/rumble)
|
59
|
+
library. Rumble gives us a simple block-based syntax for generating HTML
|
60
|
+
fragments. Here's a small example:
|
61
|
+
|
62
|
+
``` ruby
|
63
|
+
build_html do
|
64
|
+
div :id => :content do
|
65
|
+
h1 'Hello World', :class => :main
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Becomes:
|
71
|
+
|
72
|
+
``` html
|
73
|
+
<div id="content">
|
74
|
+
<h1 class="main">Hello World</h1>
|
75
|
+
</div>
|
76
|
+
```
|
77
|
+
|
78
|
+
You can use tag helpers like `div`, `span`, and `a` only within a block passed
|
79
|
+
to the `build_html` method. The `build_html` method returns a safe string. See
|
80
|
+
[the documentation for `Keynote::Rumble`](http://rubydoc.info/gems/keynote/Keynote/Rumble)
|
81
|
+
for more information.
|
82
|
+
|
83
|
+
### A more complex example
|
84
|
+
|
85
|
+
Let's add to our original example by introducing a named presenter. In addition
|
86
|
+
to `UserPresenter`, which has general-purpose methods for displaying the User
|
87
|
+
model, we'll create `HeaderPresenter`, which has methods that are specific to
|
88
|
+
the `layouts/header` partial.
|
89
|
+
|
90
|
+
``` ruby
|
91
|
+
# app/presenters/header_presenter.rb
|
92
|
+
|
93
|
+
class HeaderPresenter < Keynote::Presenter
|
94
|
+
presents :user
|
95
|
+
|
96
|
+
def profile_or_login_link
|
97
|
+
if logged_in? # defined in a helper
|
98
|
+
profile_link
|
99
|
+
else
|
100
|
+
login_link
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def profile_link
|
105
|
+
build_html do
|
106
|
+
div class: 'profile_link' do
|
107
|
+
k(user).profile_link
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def login_link
|
113
|
+
build_html do
|
114
|
+
div class: 'login_link' do
|
115
|
+
link_to 'Log In', login_url
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
``` erb
|
123
|
+
<%# app/layouts/_header.html.erb %>
|
124
|
+
|
125
|
+
<% header = present(:header, current_user) %>
|
126
|
+
|
127
|
+
<div id="header">
|
128
|
+
...
|
129
|
+
<%= header.profile_or_login_link %>
|
130
|
+
</div>
|
131
|
+
```
|
132
|
+
|
133
|
+
We've avoided putting a conditional in the template, and we've also avoided
|
134
|
+
exposing the `profile_or_login_link` method to other parts of the app that
|
135
|
+
shouldn't need to care about it. It's located in a class that's specific to
|
136
|
+
this context.
|
137
|
+
|
138
|
+
### Delegating to models
|
139
|
+
|
140
|
+
If you want to delegate some calls on the presenter to one of the presenter's
|
141
|
+
underlying objects, it's easy to do it explicitly with ActiveSupport's
|
142
|
+
`delegate` API.
|
143
|
+
|
144
|
+
``` ruby
|
145
|
+
# app/presenters/user_presenter.rb
|
146
|
+
|
147
|
+
class UserPresenter < Keynote::Presenter
|
148
|
+
presents :user
|
149
|
+
delegate :first_name, :last_name, :to => :user
|
150
|
+
|
151
|
+
def display_name
|
152
|
+
"#{first_name} #{last_name}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
You can also generate prefixed methods like `user_first_name` by passing
|
158
|
+
`:prefix => true` to the `delegate` method.
|
159
|
+
|
160
|
+
## Rationale
|
161
|
+
|
162
|
+
### Why use presenters or decorators at all?
|
163
|
+
|
164
|
+
The main alternative is to use helpers. Helpers are fine for many use cases --
|
165
|
+
Rails' built-in tag and form helpers are great. They have some drawbacks,
|
166
|
+
though:
|
167
|
+
|
168
|
+
* Every helper method you write gets mixed into the same view object as the
|
169
|
+
built-in Rails helpers, URL generators, and all the other junk that comes
|
170
|
+
along with `ActionView::Base`. In a freshly-generated Rails project:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
>> ApplicationController.new.view_context.public_methods.count
|
174
|
+
=> 318
|
175
|
+
>> ApplicationController.new.view_context.private_methods.count
|
176
|
+
=> 119
|
177
|
+
```
|
178
|
+
|
179
|
+
* Helpers can't have state that isn't "global" relative to the view, which
|
180
|
+
can make it hard to write helpers that work together.
|
181
|
+
|
182
|
+
* By default, every helper is available in every view. This makes it difficult
|
183
|
+
to set boundaries between different parts of your app and organize your view
|
184
|
+
code cleanly.
|
185
|
+
|
186
|
+
### Why not use decorators?
|
187
|
+
|
188
|
+
The biggest distinction between Keynote and similar libraries like
|
189
|
+
[Draper](https://github.com/drapergem/draper) and
|
190
|
+
[DisplayCase](https://github.com/avdi/display-case) is that Keynote
|
191
|
+
presenters aren't decorators -- undefined method calls don't
|
192
|
+
fall through to an underlying model.
|
193
|
+
|
194
|
+
Applying the Decorator pattern to generating views is a reasonable thing to do.
|
195
|
+
However, this practice also has some downsides.
|
196
|
+
|
197
|
+
* Decorators make the most sense when there's exactly one object that's
|
198
|
+
relevant to the methods you want to encapsulate. They're less helpful when
|
199
|
+
you want to do things like define a class whose responsibility is to help
|
200
|
+
render a specific part of your user interface, which may involve bringing in
|
201
|
+
data from multiple models or collections.
|
202
|
+
|
203
|
+
* When reading code that uses decorators, it often isn't obvious if a given
|
204
|
+
method is defined on the decorator or the underlying model, especially when
|
205
|
+
the decorator is applied in the controller instead of the view.
|
206
|
+
|
207
|
+
* Passing decorated models between controllers and views can make it unclear
|
208
|
+
whether a view (especially a nested partial) depends on a model having some
|
209
|
+
specific decorator applied to it. This makes refactoring view and decorator
|
210
|
+
code harder than it needs to be.
|
211
|
+
|
212
|
+
## Generators
|
213
|
+
|
214
|
+
Keynote doesn't automatically generate presenters when you generate models or
|
215
|
+
resources. To generate a presenter, you can use the `presenter` generator,
|
216
|
+
like so:
|
217
|
+
|
218
|
+
``` bash
|
219
|
+
$ rails g presenter FooBar foo bar
|
220
|
+
create app/presenters/foo_bar_presenter.rb
|
221
|
+
create spec/presenters/foo_bar_presenter_spec.rb
|
222
|
+
```
|
223
|
+
|
224
|
+
That project uses RSpec, but the generator can also create test files for
|
225
|
+
Test::Unit or MiniTest::Rails if applicable.
|
226
|
+
|
227
|
+
## Compatibility
|
228
|
+
|
229
|
+
Keynote is supported on Rails 3.0, 3.1, 3.2, and 4.0. Keynote presenters are
|
230
|
+
testable with Test::Unit, RSpec, and MiniTest::Rails.
|
231
|
+
|
232
|
+
If you find problems with any of the above integrations, please open an issue.
|
233
|
+
|
234
|
+
## Development
|
235
|
+
|
236
|
+
You can run Keynote's tests across all supported versions of Rails as follows:
|
237
|
+
|
238
|
+
``` bash
|
239
|
+
$ bundle install
|
240
|
+
$ rake appraisal:gemfiles
|
241
|
+
$ rake appraisal:install
|
242
|
+
$ rake appraisal
|
243
|
+
```
|
244
|
+
|
245
|
+
Feel free to submit pull requests according to the usual conventions for Ruby
|
246
|
+
projects.
|
data/lib/keynote.rb
CHANGED
@@ -8,8 +8,17 @@ require "keynote/helper"
|
|
8
8
|
require "keynote/railtie"
|
9
9
|
require "keynote/cache"
|
10
10
|
|
11
|
+
# Keynote is a library for defining and instantiating presenters,
|
12
|
+
# objects that encapsulate view logic.
|
13
|
+
#
|
14
|
+
# @see file:README.md
|
11
15
|
module Keynote
|
12
16
|
class << self
|
17
|
+
# @return [Boolean] When `use_caching` is enabled, repeatedly invoking
|
18
|
+
# the same presenter with the same parameters will always return the
|
19
|
+
# same object. This is disabled by default for now.
|
20
|
+
attr_accessor :use_caching
|
21
|
+
|
13
22
|
# Create or retrieve a presenter wrapping zero or more objects.
|
14
23
|
#
|
15
24
|
# The first parameter is a Rails view context, but you'll usually access
|
@@ -47,7 +56,11 @@ module Keynote
|
|
47
56
|
name = presenter_name_from_object(objects[0])
|
48
57
|
end
|
49
58
|
|
50
|
-
|
59
|
+
if Keynote.use_caching
|
60
|
+
Cache.fetch(name, view, *objects) do
|
61
|
+
presenter_from_name(name).new(view, *objects)
|
62
|
+
end
|
63
|
+
else
|
51
64
|
presenter_from_name(name).new(view, *objects)
|
52
65
|
end
|
53
66
|
end
|
@@ -62,4 +75,6 @@ module Keynote
|
|
62
75
|
"#{name.to_s.camelize}Presenter".constantize
|
63
76
|
end
|
64
77
|
end
|
78
|
+
|
79
|
+
Keynote.use_caching = false
|
65
80
|
end
|
data/lib/keynote/controller.rb
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
|
3
3
|
module Keynote
|
4
4
|
# `Keynote::Controller` is mixed into `ActionController::Base` and
|
5
|
-
# `ActionMailer::Base`, providing a `present` method for
|
6
|
-
# presenters.
|
5
|
+
# `ActionMailer::Base`, providing a `present` method (aliased to `k`) for
|
6
|
+
# instantiating presenters.
|
7
7
|
module Controller
|
8
8
|
# Instantiate a presenter.
|
9
9
|
# @see Keynote.present
|
10
10
|
def present(*objects)
|
11
11
|
Keynote.present(view_context, *objects)
|
12
12
|
end
|
13
|
+
alias k present
|
13
14
|
end
|
14
15
|
end
|
data/lib/keynote/helper.rb
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module Keynote
|
4
4
|
# `Keynote::Helper` is mixed into `ActionView::Base`, providing a `present`
|
5
|
-
# method (aliased to `
|
5
|
+
# method (aliased to `k`) for instantiating presenters.
|
6
6
|
module Helper
|
7
7
|
# Instantiate a presenter.
|
8
8
|
# @see Keynote.present
|
9
9
|
def present(*objects)
|
10
10
|
Keynote.present(self, *objects)
|
11
11
|
end
|
12
|
-
alias
|
12
|
+
alias k present
|
13
13
|
end
|
14
14
|
end
|
data/lib/keynote/presenter.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
module Keynote
|
4
|
+
# Keynote::Presenter is a base class for presenters, objects that encapsulate
|
5
|
+
# view logic.
|
6
|
+
#
|
7
|
+
# @see file:README.md
|
4
8
|
class Presenter
|
5
9
|
include Keynote::Rumble
|
6
10
|
|
@@ -20,7 +24,7 @@ module Keynote
|
|
20
24
|
# end
|
21
25
|
#
|
22
26
|
# # In a view
|
23
|
-
# presenter =
|
27
|
+
# presenter = k(:post, @some_post, @some_user)
|
24
28
|
# presenter.blog_post # == @some_post
|
25
29
|
# presenter.author # == @some_user
|
26
30
|
#
|
@@ -55,7 +59,7 @@ module Keynote
|
|
55
59
|
def present(*objects)
|
56
60
|
Keynote.present(@view, *objects)
|
57
61
|
end
|
58
|
-
alias
|
62
|
+
alias k present
|
59
63
|
|
60
64
|
# @private
|
61
65
|
def respond_to_missing?(method_name, include_private = true)
|
data/lib/keynote/rumble.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Keynote
|
4
4
|
# HTML markup in Ruby.
|
5
5
|
#
|
6
|
-
# To invoke Rumble, call the `
|
6
|
+
# To invoke Rumble, call the `build_html` method in a presenter.
|
7
7
|
#
|
8
8
|
# ## 1. Syntax
|
9
9
|
#
|
@@ -26,7 +26,7 @@ module Keynote
|
|
26
26
|
# Example:
|
27
27
|
#
|
28
28
|
# ``` ruby
|
29
|
-
#
|
29
|
+
# build_html do
|
30
30
|
# div :id => :content do
|
31
31
|
# h1 'Hello World', :class => :main
|
32
32
|
# end
|
@@ -133,7 +133,7 @@ module Keynote
|
|
133
133
|
# presents :article
|
134
134
|
#
|
135
135
|
# def published_at
|
136
|
-
#
|
136
|
+
# build_html do
|
137
137
|
# div.published_at do
|
138
138
|
# span.date publication_date
|
139
139
|
# span.time publication_time
|
@@ -321,8 +321,8 @@ module Keynote
|
|
321
321
|
end
|
322
322
|
|
323
323
|
# Generate HTML using Rumble tag methods. If tag methods are called
|
324
|
-
# outside
|
325
|
-
def
|
324
|
+
# outside a `build_html` block, they'll raise an exception.
|
325
|
+
def build_html
|
326
326
|
ctx = @rumble_context
|
327
327
|
@rumble_context = Context.new
|
328
328
|
yield
|
data/lib/keynote/version.rb
CHANGED
data/spec/helper.rb
CHANGED
@@ -51,7 +51,7 @@ class NormalPresenter < Keynote::Presenter
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def some_bad_html
|
54
|
-
|
54
|
+
build_html do
|
55
55
|
div { text some_bad_js }
|
56
56
|
div { some_bad_js }
|
57
57
|
div some_bad_js
|
@@ -67,7 +67,7 @@ module Keynote
|
|
67
67
|
presents :model
|
68
68
|
|
69
69
|
def generate_div
|
70
|
-
|
70
|
+
build_html do
|
71
71
|
div.hi! do
|
72
72
|
link_to '#', 'Hello'
|
73
73
|
end
|
data/spec/keynote_spec.rb
CHANGED
@@ -58,41 +58,60 @@ describe Keynote do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
describe "
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
describe "caching" do
|
62
|
+
describe "enabled" do
|
63
|
+
before { Keynote.use_caching = true }
|
64
|
+
after { Keynote.use_caching = false }
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
it "should cache on the model instance(s)" do
|
67
|
+
model_1 = Normal.new
|
68
|
+
model_2 = Normal.new
|
68
69
|
|
69
|
-
|
70
|
+
presented_1 = Keynote.present(:view, model_1)
|
71
|
+
presented_2 = Keynote.present(:view, model_1)
|
70
72
|
|
71
|
-
|
72
|
-
presented_4 = Keynote.present(:view, :combined, model_1, model_2)
|
73
|
-
presented_5 = Keynote.present(:view, :combined, model_2, model_1)
|
73
|
+
presented_1.must_be :equal?, presented_2
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
presented_3 = Keynote.present(:view, :combined, model_1, model_2)
|
76
|
+
presented_4 = Keynote.present(:view, :combined, model_1, model_2)
|
77
|
+
presented_5 = Keynote.present(:view, :combined, model_2, model_1)
|
78
|
+
|
79
|
+
presented_3.wont_be :equal?, presented_1
|
80
|
+
presented_3.must_be :equal?, presented_4
|
81
|
+
presented_3.wont_be :equal?, presented_5
|
82
|
+
end
|
83
|
+
|
84
|
+
it "shouldn't cache if there are no models" do
|
85
|
+
presenter_1 = Keynote.present(:view, :empty)
|
86
|
+
presenter_2 = Keynote.present(:view, :empty)
|
79
87
|
|
80
|
-
|
81
|
-
|
82
|
-
presenter_2 = Keynote.present(:view, :empty)
|
88
|
+
presenter_1.wont_be :equal?, presenter_2
|
89
|
+
end
|
83
90
|
|
84
|
-
|
91
|
+
it "should update the view every time" do
|
92
|
+
model = Normal.new
|
93
|
+
|
94
|
+
presenter_1 = Keynote.present(:view, model)
|
95
|
+
presenter_1.view.must_equal :view
|
96
|
+
|
97
|
+
presenter_2 = Keynote.present(:view_2, model)
|
98
|
+
presenter_2.must_be :equal?, presenter_1
|
99
|
+
presenter_2.view.must_equal :view_2
|
100
|
+
end
|
85
101
|
end
|
86
102
|
|
87
|
-
|
88
|
-
|
103
|
+
describe "disabled" do
|
104
|
+
before { Keynote.use_caching = false }
|
105
|
+
|
106
|
+
it "shouldn't cache" do
|
107
|
+
model_1 = Normal.new
|
108
|
+
model_2 = Normal.new
|
89
109
|
|
90
|
-
|
91
|
-
|
110
|
+
presented_1 = Keynote.present(:view, model_1)
|
111
|
+
presented_2 = Keynote.present(:view, model_1)
|
92
112
|
|
93
|
-
|
94
|
-
|
95
|
-
presenter_2.view.must_equal :view_2
|
113
|
+
presented_1.wont_be :equal?, presented_2
|
114
|
+
end
|
96
115
|
end
|
97
116
|
end
|
98
117
|
end
|
data/spec/railtie_spec.rb
CHANGED
@@ -6,13 +6,14 @@ describe Keynote::Railtie do
|
|
6
6
|
let(:controller) { HelloController.new }
|
7
7
|
let(:context) { controller.view_context }
|
8
8
|
|
9
|
-
it "should make the present
|
9
|
+
it "should make the present and k methods available to controllers" do
|
10
10
|
controller.must_respond_to :present
|
11
|
+
controller.must_respond_to :k
|
11
12
|
end
|
12
13
|
|
13
|
-
it "should make the present and
|
14
|
+
it "should make the present and k methods available to views" do
|
14
15
|
context.must_respond_to :present
|
15
|
-
context.must_respond_to :
|
16
|
+
context.must_respond_to :k
|
16
17
|
end
|
17
18
|
|
18
19
|
it "should pass present call from controller to Keynote.present" do
|
data/spec/rumble_spec.rb
CHANGED
@@ -12,7 +12,7 @@ class TestRumble < MiniTest::Unit::TestCase
|
|
12
12
|
def assert_rumble(str, &blk)
|
13
13
|
exp = str.gsub(/(\s+(<)|>\s+)/) { $2 || '>' }
|
14
14
|
res = nil
|
15
|
-
|
15
|
+
build_html {
|
16
16
|
res = yield.to_s
|
17
17
|
}
|
18
18
|
assert_equal exp, res
|
@@ -79,16 +79,16 @@ class TestRumble < MiniTest::Unit::TestCase
|
|
79
79
|
|
80
80
|
assert_rumble str do
|
81
81
|
div do
|
82
|
-
(%w[Hello World].map { |x|
|
82
|
+
(%w[Hello World].map { |x| build_html { p x; p x } } * '|').html_safe
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
def test_capture_raise
|
88
88
|
assert_raises RuntimeError do
|
89
|
-
|
89
|
+
build_html {
|
90
90
|
div do
|
91
|
-
|
91
|
+
build_html { raise }
|
92
92
|
end
|
93
93
|
}
|
94
94
|
end
|
@@ -174,7 +174,7 @@ class TestRumble < MiniTest::Unit::TestCase
|
|
174
174
|
|
175
175
|
def test_error_selfclosing_content
|
176
176
|
assert_raises Rumble::Error do
|
177
|
-
|
177
|
+
build_html {
|
178
178
|
br "content"
|
179
179
|
}
|
180
180
|
end
|
@@ -182,7 +182,7 @@ class TestRumble < MiniTest::Unit::TestCase
|
|
182
182
|
|
183
183
|
def test_error_css_proxy_continue
|
184
184
|
assert_raises Rumble::Error do
|
185
|
-
|
185
|
+
build_html {
|
186
186
|
p.one("test").two
|
187
187
|
}
|
188
188
|
end
|
@@ -191,7 +191,7 @@ class TestRumble < MiniTest::Unit::TestCase
|
|
191
191
|
# The real test here is if @rumble_context is nil in the teardown.
|
192
192
|
def test_error_general
|
193
193
|
assert_raises RuntimeError do
|
194
|
-
|
194
|
+
build_html {
|
195
195
|
div do
|
196
196
|
raise
|
197
197
|
end
|
metadata
CHANGED
@@ -1,128 +1,128 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keynote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
5
4
|
prerelease:
|
5
|
+
version: 0.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ryan Fitzgerald
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 3.0.0
|
20
|
+
none: false
|
21
|
+
name: rails
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
|
25
|
-
none: false
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
26
25
|
requirements:
|
27
26
|
- - ! '>='
|
28
27
|
- !ruby/object:Gem::Version
|
29
28
|
version: 3.0.0
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: appraisal
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
29
|
none: false
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
version_requirements: !ruby/object:Gem::Requirement
|
34
32
|
requirements:
|
35
33
|
- - ! '>='
|
36
34
|
- !ruby/object:Gem::Version
|
37
35
|
version: '0'
|
36
|
+
none: false
|
37
|
+
name: appraisal
|
38
38
|
type: :development
|
39
39
|
prerelease: false
|
40
|
-
|
41
|
-
none: false
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
42
41
|
requirements:
|
43
42
|
- - ! '>='
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
version: '0'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: minitest
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
45
|
none: false
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
48
|
requirements:
|
51
49
|
- - ! '>='
|
52
50
|
- !ruby/object:Gem::Version
|
53
51
|
version: '0'
|
52
|
+
none: false
|
53
|
+
name: minitest
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
|
-
|
57
|
-
none: false
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
58
|
- - ! '>='
|
60
59
|
- !ruby/object:Gem::Version
|
61
60
|
version: '0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: mocha
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
61
|
none: false
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
64
|
requirements:
|
67
65
|
- - ! '>='
|
68
66
|
- !ruby/object:Gem::Version
|
69
67
|
version: '0'
|
68
|
+
none: false
|
69
|
+
name: mocha
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
|
-
|
73
|
-
none: false
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
74
73
|
requirements:
|
75
74
|
- - ! '>='
|
76
75
|
- !ruby/object:Gem::Version
|
77
76
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: pry
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
77
|
none: false
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
80
|
requirements:
|
83
81
|
- - ! '>='
|
84
82
|
- !ruby/object:Gem::Version
|
85
83
|
version: '0'
|
84
|
+
none: false
|
85
|
+
name: pry
|
86
86
|
type: :development
|
87
87
|
prerelease: false
|
88
|
-
|
89
|
-
none: false
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
90
89
|
requirements:
|
91
90
|
- - ! '>='
|
92
91
|
- !ruby/object:Gem::Version
|
93
92
|
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: redcarpet
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
93
|
none: false
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
96
|
requirements:
|
99
97
|
- - ! '>='
|
100
98
|
- !ruby/object:Gem::Version
|
101
99
|
version: '0'
|
100
|
+
none: false
|
101
|
+
name: redcarpet
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
|
-
|
105
|
-
none: false
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
106
105
|
requirements:
|
107
106
|
- - ! '>='
|
108
107
|
- !ruby/object:Gem::Version
|
109
108
|
version: '0'
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: yard
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
109
|
none: false
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
112
|
requirements:
|
115
113
|
- - ! '>='
|
116
114
|
- !ruby/object:Gem::Version
|
117
115
|
version: '0'
|
116
|
+
none: false
|
117
|
+
name: yard
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
|
-
|
121
|
-
none: false
|
120
|
+
requirement: !ruby/object:Gem::Requirement
|
122
121
|
requirements:
|
123
122
|
- - ! '>='
|
124
123
|
- !ruby/object:Gem::Version
|
125
124
|
version: '0'
|
125
|
+
none: false
|
126
126
|
description: ''
|
127
127
|
email:
|
128
128
|
- rwfitzge@gmail.com
|
@@ -170,23 +170,17 @@ rdoc_options: []
|
|
170
170
|
require_paths:
|
171
171
|
- lib
|
172
172
|
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
-
none: false
|
174
173
|
requirements:
|
175
174
|
- - ! '>='
|
176
175
|
- !ruby/object:Gem::Version
|
177
176
|
version: '0'
|
178
|
-
segments:
|
179
|
-
- 0
|
180
|
-
hash: -4215378202038736203
|
181
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
177
|
none: false
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
179
|
requirements:
|
184
180
|
- - ! '>='
|
185
181
|
- !ruby/object:Gem::Version
|
186
182
|
version: '0'
|
187
|
-
|
188
|
-
- 0
|
189
|
-
hash: -4215378202038736203
|
183
|
+
none: false
|
190
184
|
requirements: []
|
191
185
|
rubyforge_project:
|
192
186
|
rubygems_version: 1.8.24
|