effigy 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -36,10 +36,10 @@ class PostView < Effigy::View
36
36
  text('h1', post.title)
37
37
  text('title', "#{post.title} - Site title")
38
38
  text('p.body', post.body)
39
- replace_with_each('.comment', post.comments) do |comment|
39
+ replace_each('.comment', post.comments) do |comment|
40
40
  text('h2', comment.title)
41
41
  text('p', comment.summary)
42
- attributes('a', :href => url_for(comment))
42
+ attr('a', :href => url_for(comment))
43
43
  end
44
44
  remove('#no-comments') if post.comments.empty?
45
45
  end
@@ -72,6 +72,34 @@ document = view.render(template)
72
72
 
73
73
  See the documentation for more information on available transformations.
74
74
 
75
+ h2. Chaining
76
+
77
+ If you prefer, you can select elements and then apply tranformations in a chain. The previous example could have been written like this:
78
+
79
+ <pre>
80
+ class PostView < Effigy::View
81
+ attr_reader :post
82
+
83
+ def initialize(post)
84
+ @post = post
85
+ end
86
+
87
+ def transform
88
+ find('h1').text(post.title)
89
+ find('title').text("#{post.title} - Site title")
90
+ find('p.body').text(post.body)
91
+ find('.comment').replace_each(post.comments) do |comment|
92
+ find('h2').text(comment.title)
93
+ find('p').text(comment.summary)
94
+ find('a').attr(:href => url_for(comment))
95
+ end
96
+ find('#no-comments').remove if post.comments.empty?
97
+ end
98
+ end
99
+ </pre>
100
+
101
+ #find is also aliased as #f for brevity, if you're into that sort of thing.
102
+
75
103
  h2. Rails
76
104
 
77
105
  Effigy integrates with Rails. It provides a view subclass that copies instance variables from the controller, a template handler to find Effigy views and templates, and a generator to create skeleton view files.
@@ -103,11 +131,21 @@ end
103
131
 
104
132
  View this example in your browser and you'll see "hocus pocus."
105
133
 
134
+ h2. Install
135
+
136
+ Effigy is distributed as a gem through gemcutter:
137
+
138
+ <pre>
139
+ sudo gem install effigy -s http://gemcutter.org
140
+ </pre>
141
+
142
+ Effigy requires Nokogiri.
143
+
106
144
  h2. Why?
107
145
 
108
146
  Effigy is based on the idea that putting behavior in your templates is confusing and makes them difficult to maintain, and that the closer an ERB template gets to 50% Ruby, 50% HTML, the closer it gets to total chaos. Complicated views require unintuitive concepts (ERB buffers, capture blocks, etc). ERB also has the constant threat of unescaped user input slipping into a view.
109
147
 
110
- Effigy was created because I have never liked interpolation-based templating languages like ERB and because XSLT is a new language (and I like Ruby just fine).
148
+ Effigy was created because I have never liked interpolation-based templating languages like ERB and because XSLT requires introducing another language (and I like Ruby just fine).
111
149
 
112
150
  h2. Author
113
151
 
data/Rakefile CHANGED
@@ -55,6 +55,8 @@ begin
55
55
  gem.email = %q{jferris@thoughtbot.com}
56
56
 
57
57
  gem.platform = Gem::Platform::RUBY
58
+
59
+ gem.add_runtime_dependency 'nokogiri'
58
60
  end
59
61
  Jeweler::GemcutterTasks.new
60
62
  rescue LoadError
data/TODO.textile ADDED
@@ -0,0 +1,5 @@
1
+ * Implement more jQuery manipulation methods
2
+ * Handle Rails layouts specially
3
+ * Find a replacement for Rails partials
4
+ * Include ActionView helpers that don't generate markup
5
+ * Replace ActionView helpers taht generate markup
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
data/lib/effigy.rb CHANGED
@@ -1,3 +1,8 @@
1
1
  require 'effigy/view'
2
2
  require 'effigy/errors'
3
3
 
4
+ # Namespace module for Effigy.
5
+ #
6
+ # See {file:README.textile the README}, {View}, or {Rails}.
7
+ module Effigy
8
+ end
@@ -1,17 +1,26 @@
1
1
  require 'nokogiri'
2
2
 
3
3
  module Effigy
4
+ # Internal use only.
5
+ #
6
+ # Used when parsing and manipulating lists of CSS class names.
4
7
  class ClassList
8
+ # @param element [Nokogiri::XML::Element] the element whose class names
9
+ # should be manipulated
5
10
  def initialize(element)
6
11
  @element = element
7
12
  read_class_names
8
13
  end
9
14
 
15
+ # Appends a class name to the list.
16
+ # @param [String] class_name the class name to append
10
17
  def <<(class_name)
11
18
  @class_names << class_name
12
19
  write_class_names
13
20
  end
14
21
 
22
+ # Removes a class name from the list.
23
+ # @param [String] class_name the class name to remove
15
24
  def remove(class_name)
16
25
  @class_names.delete(class_name)
17
26
  write_class_names
@@ -19,10 +28,12 @@ module Effigy
19
28
 
20
29
  private
21
30
 
31
+ # Parses and caches the list of class names. Called after initialization.
22
32
  def read_class_names
23
33
  @class_names = (@element['class'] || '').split(' ')
24
34
  end
25
35
 
36
+ # Writes the transformed list of classes to the element's class attribute.
26
37
  def write_class_names
27
38
  @element['class'] = @class_names.join(' ')
28
39
  end
@@ -0,0 +1,11 @@
1
+ # Internal use only.
2
+ #
3
+ # Extends Hash to easily convert a hash or key, value pair to a hash.
4
+ class Hash
5
+ # @return [Hash] self
6
+ # @param [Object] value ignored
7
+ # @see Object#to_effigy_attributes
8
+ def to_effigy_attributes(value)
9
+ self
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # Internal use only.
2
+ #
3
+ # Extends Object to easily convert a hash or key, value pair to a hash.
4
+ class Object
5
+ # @return [Hash] a hash composed of the object as the key and the given value
6
+ # as the value.
7
+ # @param [Object] value the value to use in the generated hash
8
+ # @see Hash#to_effigy_attributes
9
+ def to_effigy_attributes(value)
10
+ { self => value }
11
+ end
12
+ end
data/lib/effigy/errors.rb CHANGED
@@ -1,11 +1,16 @@
1
1
  module Effigy
2
+ # Raised when attempting to select an element that isn't on the source
3
+ # template.
2
4
  class ElementNotFound < StandardError
5
+ # [String] The selector that didn't match any elements
3
6
  attr_accessor :selector
4
7
 
8
+ # @param [String] the selector that didn't match any elements
5
9
  def initialize(selector)
6
10
  @selector = selector
7
11
  end
8
12
 
13
+ # @return [String] a description of the failed search
9
14
  def message
10
15
  "No element matched the given selector: #{selector.inspect}"
11
16
  end
@@ -0,0 +1,39 @@
1
+ module Effigy
2
+ # Proxy class for performing transformations with a set selection.
3
+ #
4
+ # Selections are created and returned when calling {View#find} without a
5
+ # block. Any methods called on the Selection will be forwarded to the given
6
+ # view with the given selector inserted at the front of the argument list.
7
+ #
8
+ # All methods should return the Selection itself, so transformation methods
9
+ # can be chained on a selection.
10
+ #
11
+ # Normally, Selections are not instantiated directly, but by calling
12
+ # {View#find}.
13
+ #
14
+ # @example
15
+ # view = Effigy::View.new
16
+ # # same as calling view.remove_class('.active', 'inactive')
17
+ # view.find('.active').remove_class('inactive')
18
+ class Selection
19
+
20
+ # Creates a selection over the given view using the given selector.
21
+ # @param view [View] the view to which transformations should be forwarded
22
+ # @param selector [String] the selector that should be used for forwarded
23
+ # transformation methods
24
+ def initialize(view, selector)
25
+ @view = view
26
+ @selector = selector
27
+ end
28
+
29
+ # Undefined methods are forwarded to the view with the selector inserted at
30
+ # the beginning of the argument list. The Selection is then returned for
31
+ # chaining.
32
+ #
33
+ # @return [Selection] self
34
+ def method_missing(method, *args, &block)
35
+ @view.send(method, @selector, *args, &block)
36
+ self
37
+ end
38
+ end
39
+ end
data/lib/effigy/view.rb CHANGED
@@ -1,21 +1,72 @@
1
1
  require 'nokogiri'
2
2
  require 'effigy/class_list'
3
3
  require 'effigy/errors'
4
+ require 'effigy/selection'
4
5
 
5
6
  module Effigy
7
+ # Accepts a template to be transformed.
8
+ #
9
+ # For most common cases, creating a subclass makes the most sense, but this
10
+ # class can be used directly by passing a block to {#render}.
11
+ #
12
+ # @see #transform
13
+ # @see #render
14
+ # @example
15
+ # view = Effigy::View.new
16
+ # view.render(template) do
17
+ # view.find('h1').text('the title')
18
+ # end
19
+ #
6
20
  class View
21
+ # Replaces the text content of the selected element.
22
+ #
23
+ # Markup in the given content is escaped. Use {#html} if you want to
24
+ # replace the contents with live markup.
25
+ #
26
+ # @param [String] selector a CSS or XPath string describing the element to
27
+ # transform
28
+ # @param [String] content the text that should be the new element contents
29
+ # @example
30
+ # text('h1', 'a title')
31
+ # find('h1').text('a title')
32
+ # text('p', '<b>title</b>') # <p>&lt;b&gt;title&lt;/title&gt;</p>
7
33
  def text(selector, content)
8
34
  select(selector).content = content
9
35
  end
10
36
 
11
- def attributes(selector, attributes)
37
+ # Adds or updates the given attribute or attributes of the selected element.
38
+ #
39
+ # @param [String] selector a CSS or XPath string describing the element to
40
+ # transform
41
+ # @param [String,Hash] attributes_or_attribute_name if a String, replaces
42
+ # that attribute with the given value. If a Hash, uses the keys as
43
+ # attribute names and values as attribute values
44
+ # @param [String] value the value for the replaced attribute. Used only if
45
+ # attributes_or_attribute_name is a String
46
+ # @example
47
+ # attr('p', :id => 'an_id', :style => 'display: none')
48
+ # attr('p', :id, 'an_id')
49
+ # find('p').attr(:id, 'an_id')
50
+ def attr(selector, attributes_or_attribute_name, value = nil)
12
51
  element = select(selector)
52
+ attributes = attributes_or_attribute_name.to_effigy_attributes(value)
13
53
  attributes.each do |attribute, value|
14
54
  element[attribute.to_s] = value
15
55
  end
16
56
  end
17
57
 
18
- def replace_with_each(selector, collection, &block)
58
+ # Replaces the selected element with a clone for each item in the collection.
59
+ #
60
+ # @param [String] selector a CSS or XPath string describing the element to
61
+ # transform
62
+ # @param [Enumerable] collection the items that are the base for each
63
+ # cloned element
64
+ # @example
65
+ # titles = %w(one two three)
66
+ # find('.post').replace_each(titles) do |title|
67
+ # text('h1', title)
68
+ # end
69
+ def replace_each(selector, collection, &block)
19
70
  original_element = select(selector)
20
71
  collection.inject(original_element) do |sibling, item|
21
72
  item_element = clone_element_with_item(original_element, item, &block)
@@ -24,6 +75,13 @@ module Effigy
24
75
  original_element.unlink
25
76
  end
26
77
 
78
+ # Perform transformations on the given template.
79
+ #
80
+ # @yield inside the given block, transformation methods such as #text and
81
+ # #html can be used on the template. Using a subclass, you can instead
82
+ # override the #transform method, which is the preferred approach.
83
+ #
84
+ # @return [String] the resulting document
27
85
  def render(template)
28
86
  @current_context = Nokogiri::XML.parse(template)
29
87
  yield if block_given?
@@ -31,44 +89,141 @@ module Effigy
31
89
  output
32
90
  end
33
91
 
34
- def context(new_context)
35
- old_context = @current_context
36
- @current_context = select(new_context)
37
- yield
38
- @current_context = old_context
39
- end
40
-
92
+ # Removes the selected elements from the template.
93
+ #
94
+ # @param [String] selector a CSS or XPath string describing the element to
95
+ # transform
96
+ # @example
97
+ # remove('.post')
98
+ # find('.post').remove
41
99
  def remove(selector)
42
100
  select_all(selector).each { |element| element.unlink }
43
101
  end
44
102
 
45
- def add_class_names(selector, *class_names)
103
+ # Adds the given class names to the selected element.
104
+ #
105
+ # @param [String] selector a CSS or XPath string describing the element to
106
+ # transform
107
+ # @param [String] class_names a CSS class name that should be added
108
+ # @example
109
+ # add_class('a#home', 'selected')
110
+ # find('a#home').add_class('selected')
111
+ def add_class(selector, *class_names)
46
112
  element = select(selector)
47
113
  class_list = ClassList.new(element)
48
114
  class_names.each { |class_name| class_list << class_name }
49
115
  end
50
116
 
51
- def remove_class_names(selector, *class_names)
117
+ # Removes the given class names from the selected element.
118
+ #
119
+ # Ignores class names that are not present.
120
+ #
121
+ # @param [String] selector a CSS or XPath string describing the element to
122
+ # transform
123
+ # @param [String] class_names a CSS class name that should be removed
124
+ # @example
125
+ # remove_class('a#home', 'selected')
126
+ # find('a#home').remove_class('selected')
127
+ def remove_class(selector, *class_names)
52
128
  element = select(selector)
53
129
  class_list = ClassList.new(element)
54
130
  class_names.each { |class_name| class_list.remove(class_name) }
55
131
  end
56
132
 
57
- def inner(selector, xml)
133
+ # Replaces the contents of the selected element with live markup.
134
+ #
135
+ # @param [String] selector a CSS or XPath string describing the element to
136
+ # transform
137
+ # @param [String] xml the new contents of the selected element. Markup is
138
+ # not escaped.
139
+ # @example
140
+ # html('p', '<b>Welcome!</b>')
141
+ # find('p').html('<b>Welcome!</b>')
142
+ def html(selector, xml)
58
143
  select(selector).inner_html = xml
59
144
  end
60
145
 
61
- def outer(selector, xml)
146
+ # Replaces the selected element with live markup.
147
+ #
148
+ # The "outer HTML" for the selected tag itself is also replaced.
149
+ #
150
+ # @param [String] selector a CSS or XPath string describing the element to
151
+ # transform
152
+ # @param [String] xml the new markup to replace the selected element. Markup is
153
+ # not escaped.
154
+ def replace_with(selector, xml)
62
155
  select(selector).after(xml).unlink
63
156
  end
64
157
 
65
- private
158
+ # Selects an element or elements for chained transformation.
159
+ #
160
+ # If given a block, the selection will be in effect during the block.
161
+ #
162
+ # If not given a block, a {Selection} will be returned on which
163
+ # transformation methods can be called. Any methods called on the
164
+ # Selection will be delegated back to the view with the selector inserted
165
+ # into the parameter list.
166
+ #
167
+ # @param [String] selector a CSS or XPath string describing the element to
168
+ # transform
169
+ # @return [Selection] a proxy object on which transformation methods can be
170
+ # called
171
+ # @example
172
+ # find('.post') do
173
+ # text('h1', post.title)
174
+ # text('p', post.body)
175
+ # end
176
+ # find('h1').text(post.title).add_class('active')
177
+ def find(selector)
178
+ if block_given?
179
+ old_context = @current_context
180
+ @current_context = select(selector)
181
+ yield
182
+ @current_context = old_context
183
+ else
184
+ Selection.new(self, selector)
185
+ end
186
+ end
187
+ alias_method :f, :find
66
188
 
189
+ # Called by {#render} to perform transformations on the source template.
190
+ #
191
+ # Override this method in subclasses to perform the transformations
192
+ # specific to your view.
193
+ #
194
+ # @example
195
+ # class PostView < Effigy::View
196
+ # def initialize(post)
197
+ # @post = post
198
+ # end
199
+ #
200
+ # def transform
201
+ # find('.post') do
202
+ # find('h2').text(post.title)
203
+ # find('p').text(post.body)
204
+ # end
205
+ # end
206
+ # end
67
207
  def transform
68
208
  end
69
209
 
210
+ private
211
+
212
+ # The current set of nodes on which transformations are performed.
213
+ #
214
+ # This is usually the entire document, but will be a subset of child nodes
215
+ # during {#find} blocks.
70
216
  attr_reader :current_context
71
217
 
218
+ # Returns the first node that matches the given selection, or the nodes
219
+ # themselves if given a set of nodes.
220
+ #
221
+ # @param nodes [String,Nokogiri::XML::NodeSet] if a String, the selector to
222
+ # use when determining the current context. When a NodeSet, the set of
223
+ # nodes that should be returned.
224
+ # @return [Nokogiri::XML::NodeSet] the nodes selected by the given selector
225
+ # or node set.
226
+ # @raise [ElementNotFound] if no nodes match the given selector
72
227
  def select(nodes)
73
228
  if nodes.respond_to?(:search)
74
229
  nodes
@@ -78,18 +233,39 @@ module Effigy
78
233
  end
79
234
  end
80
235
 
236
+ # Returns a set of nodes matching the given selector.
237
+ #
238
+ # @param selector [String] the selctor to use when finding nodes
239
+ # @return [Nokogiri::XML::NodeSet] the nodes selected by the given selector
240
+ # @raise [ElementNotFound] if no nodes match the given selector
81
241
  def select_all(selector)
82
242
  result = current_context.search(selector)
83
243
  raise ElementNotFound, selector if result.empty?
84
244
  result
85
245
  end
86
246
 
247
+ # Clones an element, sets it as the current context, and yields to the
248
+ # given block with the given item.
249
+ #
250
+ # @param [Nokogiri::XML::Element] the element to clone
251
+ # @param [Object] item the item that should be yielded to the block
252
+ # @yield [Object] the item passed as item
253
+ # @return [Nokogiri::XML::Element] the clone of the original element
87
254
  def clone_element_with_item(original_element, item, &block)
88
255
  item_element = original_element.dup
89
- context(item_element) { yield(item) }
256
+ find(item_element) { yield(item) }
90
257
  item_element
91
258
  end
92
259
 
260
+ # Converts the transformed document to a string.
261
+ #
262
+ # Called by {#render} after transforming the document using a passed block
263
+ # and {#transform}.
264
+ #
265
+ # Override this in subclasses if you wish to return something besides an
266
+ # XHTML string representation of the transformed document.
267
+ #
268
+ # @return [String] the transformed document as a string
93
269
  def output
94
270
  current_context.to_xhtml
95
271
  end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'effigy/core_ext/hash'
3
+
4
+ describe Hash do
5
+ it "should return itself as an attribute hash" do
6
+ hash = { :key => :value }
7
+ hash.to_effigy_attributes(nil).should == hash
8
+ end
9
+ end
10
+
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'effigy/core_ext/object'
3
+
4
+ describe Object do
5
+ it "should return itself as the key of an effigy attribute hash" do
6
+ key = :key
7
+ value = :value
8
+ key.to_effigy_attributes(value).should == { key => value }
9
+ end
10
+ end
@@ -34,7 +34,7 @@ describe "a controller with an effigy view and template" do
34
34
  create_rails_file 'app/views/layouts/application.html.effigy', <<-RUBY
35
35
  class LayoutsApplicationView < Effigy::Rails::View
36
36
  def transform
37
- inner('body', content_for(:layout))
37
+ html('body', content_for(:layout))
38
38
  end
39
39
  end
40
40
  RUBY
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'effigy/selection'
3
+
4
+ module Effigy
5
+ describe Selection do
6
+ %w(text).each do |method|
7
+ it "should delegate #{method} to its view" do
8
+ view = stub('a view')
9
+ selector = '.findme'
10
+ arguments = [1, 2, 3]
11
+ view.should_receive(method).with(selector, *arguments)
12
+ selection = Selection.new(view, selector)
13
+ selection.send(method, *arguments)
14
+ end
15
+ end
16
+
17
+ it "should return itself after delegating" do
18
+ view = stub('a view')
19
+ view.stub!(:text)
20
+ selection = Selection.new(view, '.findme')
21
+ selection.text.should == selection
22
+ end
23
+
24
+ class BlockRecorder
25
+ attr_reader :block
26
+ def run(*args, &block)
27
+ @block = block
28
+ end
29
+ end
30
+
31
+ it "should pass blocks when delegating" do
32
+ view = BlockRecorder.new
33
+ block = lambda { 'hello' }
34
+ selection = Selection.new(view, '.findme')
35
+ selection.run(&block)
36
+ view.block.should == block
37
+ end
38
+ end
39
+ end
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper'
2
2
  require 'effigy/view'
3
3
  require 'effigy/errors'
4
+ require 'effigy/core_ext/hash'
5
+ require 'effigy/core_ext/object'
4
6
 
5
7
  module Effigy
6
8
  describe View do
7
- it "should replace element contents" do
9
+ it "should replace element text" do
8
10
  template = %{<test><element one="abc">something</element></test>}
9
11
 
10
12
  view = Effigy::View.new
@@ -20,18 +22,29 @@ module Effigy
20
22
 
21
23
  view = Effigy::View.new
22
24
  xml = view.render(template) do
23
- view.attributes 'element', :one => '123', :two => '234'
25
+ view.attr 'element', :one => '123', :two => '234'
24
26
  end
25
27
 
26
28
  xml.should have_selector(:element, :contents => 'something', :one => '123', :two => '234')
27
29
  end
28
30
 
31
+ it "should replace one attribute" do
32
+ template = %{<test><element one="abc">something</element></test>}
33
+
34
+ view = Effigy::View.new
35
+ xml = view.render(template) do
36
+ view.attr 'element', :one, '123'
37
+ end
38
+
39
+ xml.should have_selector(:element, :contents => 'something', :one => '123')
40
+ end
41
+
29
42
  it "should replace an element with a clone for each item in a collection" do
30
43
  template = %{<test><element><value>original</value></element></test>}
31
44
 
32
45
  view = Effigy::View.new
33
46
  xml = view.render(template) do
34
- view.replace_with_each('element', %w(one two)) do |value|
47
+ view.replace_each('element', %w(one two)) do |value|
35
48
  view.text('value', value)
36
49
  end
37
50
  end
@@ -47,7 +60,7 @@ module Effigy
47
60
 
48
61
  view = Effigy::View.new
49
62
  xml = view.render(template) do
50
- view.context('element') do
63
+ view.find('element') do
51
64
  view.text('value', 'expected')
52
65
  end
53
66
  end
@@ -72,7 +85,7 @@ module Effigy
72
85
 
73
86
  view = Effigy::View.new
74
87
  xml = view.render(template) do
75
- view.add_class_names('test', 'one', 'two')
88
+ view.add_class('test', 'one', 'two')
76
89
  end
77
90
 
78
91
  xml.should have_selector('test.original')
@@ -85,7 +98,7 @@ module Effigy
85
98
 
86
99
  view = Effigy::View.new
87
100
  xml = view.render(template) do
88
- view.remove_class_names('test', 'one', 'two')
101
+ view.remove_class('test', 'one', 'two')
89
102
  end
90
103
 
91
104
  xml.should have_selector('test.three')
@@ -98,7 +111,7 @@ module Effigy
98
111
 
99
112
  view = Effigy::View.new
100
113
  xml = view.render(template) do
101
- view.inner 'test', '<new>replaced</new>'
114
+ view.html 'test', '<new>replaced</new>'
102
115
  end
103
116
 
104
117
  xml.should have_selector('test new', :contents => 'replaced')
@@ -110,7 +123,7 @@ module Effigy
110
123
 
111
124
  view = Effigy::View.new
112
125
  xml = view.render(template) do
113
- view.outer 'test', '<new>replaced</new>'
126
+ view.replace_with 'test', '<new>replaced</new>'
114
127
  end
115
128
 
116
129
  xml.should have_selector('new', :contents => 'replaced')
@@ -120,7 +133,20 @@ module Effigy
120
133
  it "should render xhtml by default" do
121
134
  template = %{<html/>}
122
135
  xml = Effigy::View.new.render(template)
123
- xml.should_not include('xml')
136
+ xml.should_not include('<?xml')
137
+ end
138
+
139
+ %w(find f).each do |chain_method|
140
+ it "should allow chains using #{chain_method}" do
141
+ template = %{<test><element one="abc">something</element></test>}
142
+
143
+ view = Effigy::View.new
144
+ xml = view.render(template) do
145
+ view.send(chain_method, 'element').text('expected')
146
+ end
147
+
148
+ xml.should have_selector(:element, :contents => 'expected', :one => 'abc')
149
+ end
124
150
  end
125
151
 
126
152
  describe "given a template without .find" do
@@ -136,12 +162,12 @@ module Effigy
136
162
  end
137
163
 
138
164
  it "should raise when updating attributes for .find" do
139
- render { |view| view.attributes('.find', :attr => 'value') }.
165
+ render { |view| view.attr('.find', :attr => 'value') }.
140
166
  should raise_error(Effigy::ElementNotFound)
141
167
  end
142
168
 
143
169
  it "should raise when replacing an element matching .find" do
144
- render { |view| view.replace_with_each('.find', []) }.
170
+ render { |view| view.replace_each('.find', []) }.
145
171
  should raise_error(Effigy::ElementNotFound)
146
172
  end
147
173
 
@@ -151,7 +177,7 @@ module Effigy
151
177
  end
152
178
 
153
179
  it "should raise when setting the context to .find" do
154
- render { |view| view.context('.find') }.
180
+ render { |view| view.find('.find') {} }.
155
181
  should raise_error(Effigy::ElementNotFound)
156
182
  end
157
183
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effigy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Ferris
@@ -9,10 +9,19 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-03 00:00:00 -05:00
12
+ date: 2009-11-04 00:00:00 -05:00
13
13
  default_executable:
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
16
25
  description: Define views in Ruby and templates in HTML. Avoid code interpolation or ugly templating languages. Use ids, class names, and semantic structures already present in your documents to produce content.
17
26
  email: jferris@thoughtbot.com
18
27
  executables: []
@@ -26,17 +35,24 @@ files:
26
35
  - LICENSE
27
36
  - README.textile
28
37
  - Rakefile
38
+ - TODO.textile
29
39
  - VERSION
30
40
  - lib/effigy.rb
31
41
  - lib/effigy/class_list.rb
42
+ - lib/effigy/core_ext/hash.rb
43
+ - lib/effigy/core_ext/object.rb
32
44
  - lib/effigy/errors.rb
33
45
  - lib/effigy/rails.rb
34
46
  - lib/effigy/rails/template_handler.rb
35
47
  - lib/effigy/rails/view.rb
48
+ - lib/effigy/selection.rb
36
49
  - lib/effigy/view.rb
37
50
  - spec/effigy/class_list_spec.rb
51
+ - spec/effigy/core_ext/hash_spec.rb
52
+ - spec/effigy/core_ext/object_spec.rb
38
53
  - spec/effigy/errors_spec.rb
39
54
  - spec/effigy/rails/template_handler_spec.rb
55
+ - spec/effigy/selection_spec.rb
40
56
  - spec/effigy/view_spec.rb
41
57
  - spec/rails/generators/effigy_view_spec.rb
42
58
  - spec/spec_helper.rb
@@ -71,7 +87,10 @@ specification_version: 3
71
87
  summary: Effigy provides a view and template framework without a templating language.
72
88
  test_files:
73
89
  - spec/effigy/class_list_spec.rb
90
+ - spec/effigy/core_ext/hash_spec.rb
91
+ - spec/effigy/core_ext/object_spec.rb
74
92
  - spec/effigy/errors_spec.rb
75
93
  - spec/effigy/rails/template_handler_spec.rb
94
+ - spec/effigy/selection_spec.rb
76
95
  - spec/effigy/view_spec.rb
77
96
  - spec/rails/generators/effigy_view_spec.rb