sax-machine 0.1.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +32 -0
  5. data/Gemfile +13 -2
  6. data/Guardfile +5 -0
  7. data/HISTORY.md +77 -0
  8. data/README.md +207 -0
  9. data/Rakefile +6 -20
  10. data/lib/sax-machine/{sax_ancestor_config.rb → config/sax_ancestor.rb} +3 -7
  11. data/lib/sax-machine/config/sax_attribute.rb +18 -0
  12. data/lib/sax-machine/config/sax_collection.rb +33 -0
  13. data/lib/sax-machine/{sax_element_config.rb → config/sax_element.rb} +23 -31
  14. data/lib/sax-machine/{sax_element_value_config.rb → config/sax_element_value.rb} +7 -8
  15. data/lib/sax-machine/handlers/sax_abstract_handler.rb +199 -0
  16. data/lib/sax-machine/handlers/sax_nokogiri_handler.rb +23 -0
  17. data/lib/sax-machine/handlers/sax_oga_handler.rb +39 -0
  18. data/lib/sax-machine/handlers/sax_ox_handler.rb +56 -0
  19. data/lib/sax-machine/sax_config.rb +13 -9
  20. data/lib/sax-machine/sax_configure.rb +3 -8
  21. data/lib/sax-machine/sax_document.rb +79 -49
  22. data/lib/sax-machine/version.rb +3 -0
  23. data/lib/sax-machine.rb +26 -7
  24. data/sax-machine.gemspec +20 -0
  25. data/spec/fixtures/atom-content.html +15 -0
  26. data/spec/fixtures/atom.xml +165 -0
  27. data/spec/sax-machine/sax_activerecord_spec.rb +21 -0
  28. data/spec/sax-machine/sax_configure_spec.rb +51 -0
  29. data/spec/sax-machine/sax_document_spec.rb +709 -239
  30. data/spec/sax-machine/sax_include_spec.rb +49 -0
  31. data/spec/spec_helper.rb +18 -7
  32. metadata +71 -70
  33. data/README.textile +0 -110
  34. data/lib/sax-machine/sax_attribute_config.rb +0 -40
  35. data/lib/sax-machine/sax_collection_config.rb +0 -45
  36. data/lib/sax-machine/sax_handler.rb +0 -107
  37. data/spec/sax-machine/configure_sax_machine_spec.rb +0 -53
  38. data/spec/sax-machine/include_sax_machine_spec.rb +0 -42
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "SAXMachine inheritance" do
4
+ before do
5
+ class A
6
+ include SAXMachine
7
+ element :title
8
+ end
9
+
10
+ class B < A
11
+ element :b
12
+ end
13
+
14
+ class C < B
15
+ element :c
16
+ end
17
+
18
+ xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"
19
+ @a = A.new
20
+ @a.parse xml
21
+ @b = B.new
22
+ @b.parse xml
23
+ @c = C.new
24
+ @c.parse xml
25
+ end
26
+
27
+ after do
28
+ Object.send(:remove_const, :A)
29
+ Object.send(:remove_const, :B)
30
+ Object.send(:remove_const, :C)
31
+ end
32
+
33
+ it { expect(@a).to be_a(A) }
34
+ it { expect(@a).not_to be_a(B) }
35
+ it { expect(@a).to be_a(SAXMachine) }
36
+ it { expect(@a.title).to eq("Test") }
37
+ it { expect(@b).to be_a(A) }
38
+ it { expect(@b).to be_a(B) }
39
+ it { expect(@b).to be_a(SAXMachine) }
40
+ it { expect(@b.title).to eq("Test") }
41
+ it { expect(@b.b).to eq("Matched!") }
42
+ it { expect(@c).to be_a(A) }
43
+ it { expect(@c).to be_a(B) }
44
+ it { expect(@c).to be_a(C) }
45
+ it { expect(@c).to be_a(SAXMachine) }
46
+ it { expect(@c.title).to eq("Test") }
47
+ it { expect(@c.b).to eq("Matched!") }
48
+ it { expect(@c.c).to eq("And Again") }
49
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,22 @@
1
- require 'date'
1
+ begin
2
+ require 'simplecov'
3
+ require 'coveralls'
2
4
 
3
- # gem install redgreen for colored test output
4
- begin require "redgreen" unless ENV['TM_CURRENT_LINE']
5
- rescue LoadError
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
+ SimpleCov::Formatter::HTMLFormatter,
7
+ Coveralls::SimpleCov::Formatter
8
+ ]
9
+
10
+ SimpleCov.start do
11
+ add_filter '/spec/'
12
+ end
13
+ rescue LoadError
6
14
  end
7
15
 
8
- path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
9
- $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
16
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sax-machine')
17
+ SAXMachine.handler = ENV['HANDLER'].to_sym if ENV['HANDLER']
10
18
 
11
- require "sax-machine"
19
+ RSpec.configure do |config|
20
+ config.run_all_when_everything_filtered = true
21
+ config.filter_run :focus
22
+ end
metadata CHANGED
@@ -1,97 +1,98 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sax-machine
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.2
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Paul Dix
14
8
  - Julien Kirch
9
+ - Ezekiel Templin
10
+ - Dmitry Krasnoukhov
15
11
  autorequire:
16
12
  bindir: bin
17
13
  cert_chain: []
18
-
19
- date: 2011-09-30 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: nokogiri
14
+ date: 2015-04-19 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
23
+ type: :development
23
24
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ">"
28
- - !ruby/object:Gem::Version
29
- hash: 31
30
- segments:
31
- - 0
32
- - 0
33
- - 0
34
- version: 0.0.0
35
- type: :runtime
36
- version_requirements: *id001
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
37
30
  description:
38
31
  email: paul@pauldix.net
39
32
  executables: []
40
-
41
33
  extensions: []
42
-
43
34
  extra_rdoc_files: []
44
-
45
- files:
35
+ files:
36
+ - ".gitignore"
37
+ - ".rspec"
38
+ - ".travis.yml"
39
+ - Gemfile
40
+ - Guardfile
41
+ - HISTORY.md
42
+ - README.md
43
+ - Rakefile
46
44
  - lib/sax-machine.rb
47
- - lib/sax-machine/sax_ancestor_config.rb
48
- - lib/sax-machine/sax_attribute_config.rb
45
+ - lib/sax-machine/config/sax_ancestor.rb
46
+ - lib/sax-machine/config/sax_attribute.rb
47
+ - lib/sax-machine/config/sax_collection.rb
48
+ - lib/sax-machine/config/sax_element.rb
49
+ - lib/sax-machine/config/sax_element_value.rb
50
+ - lib/sax-machine/handlers/sax_abstract_handler.rb
51
+ - lib/sax-machine/handlers/sax_nokogiri_handler.rb
52
+ - lib/sax-machine/handlers/sax_oga_handler.rb
53
+ - lib/sax-machine/handlers/sax_ox_handler.rb
49
54
  - lib/sax-machine/sax_config.rb
50
55
  - lib/sax-machine/sax_configure.rb
51
56
  - lib/sax-machine/sax_document.rb
52
- - lib/sax-machine/sax_collection_config.rb
53
- - lib/sax-machine/sax_element_config.rb
54
- - lib/sax-machine/sax_element_value_config.rb
55
- - lib/sax-machine/sax_handler.rb
56
- - README.textile
57
- - Rakefile
58
- - Gemfile
59
- - spec/spec_helper.rb
60
- - spec/sax-machine/configure_sax_machine_spec.rb
61
- - spec/sax-machine/include_sax_machine_spec.rb
57
+ - lib/sax-machine/version.rb
58
+ - sax-machine.gemspec
59
+ - spec/fixtures/atom-content.html
60
+ - spec/fixtures/atom.xml
61
+ - spec/sax-machine/sax_activerecord_spec.rb
62
+ - spec/sax-machine/sax_configure_spec.rb
62
63
  - spec/sax-machine/sax_document_spec.rb
64
+ - spec/sax-machine/sax_include_spec.rb
65
+ - spec/spec_helper.rb
63
66
  homepage: http://github.com/pauldix/sax-machine
64
- licenses: []
65
-
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
66
70
  post_install_message:
67
71
  rdoc_options: []
68
-
69
- require_paths:
72
+ require_paths:
70
73
  - lib
71
- required_ruby_version: !ruby/object:Gem::Requirement
72
- none: false
73
- requirements:
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
74
76
  - - ">="
75
- - !ruby/object:Gem::Version
76
- hash: 3
77
- segments:
78
- - 0
79
- version: "0"
80
- required_rubygems_version: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
83
81
  - - ">="
84
- - !ruby/object:Gem::Version
85
- hash: 3
86
- segments:
87
- - 0
88
- version: "0"
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
89
84
  requirements: []
90
-
91
85
  rubyforge_project:
92
- rubygems_version: 1.8.5
86
+ rubygems_version: 2.2.2
93
87
  signing_key:
94
- specification_version: 2
95
- summary: Declarative SAX Parsing with Nokogiri
96
- test_files: []
97
-
88
+ specification_version: 4
89
+ summary: Declarative SAX Parsing with Nokogiri, Ox or Oga
90
+ test_files:
91
+ - spec/fixtures/atom-content.html
92
+ - spec/fixtures/atom.xml
93
+ - spec/sax-machine/sax_activerecord_spec.rb
94
+ - spec/sax-machine/sax_configure_spec.rb
95
+ - spec/sax-machine/sax_document_spec.rb
96
+ - spec/sax-machine/sax_include_spec.rb
97
+ - spec/spec_helper.rb
98
+ has_rdoc:
data/README.textile DELETED
@@ -1,110 +0,0 @@
1
- h1. SAX Machine
2
-
3
- "http://github.com/pauldix/sax-machine/wikis":http://github.com/pauldix/sax-machine/wikis
4
-
5
- "http://github.com/pauldix/sax-machine/tree/master":http://github.com/pauldix/sax-machine/tree/master
6
-
7
- h2. Description
8
-
9
- A declarative SAX parsing library backed by Nokogiri
10
-
11
- h2. Usage
12
-
13
- <pre>
14
- require 'sax-machine'
15
-
16
- # Class for information associated with content parts in a feed.
17
- # Ex: <content type="text">sample</content>
18
- # instance.type will be "text", instance.text will be "sample"
19
- class AtomContent
20
- include SAXMachine
21
- attribute :type
22
- value :text
23
- end
24
-
25
- # Class for parsing an atom entry out of a feedburner atom feed
26
- class AtomEntry
27
- include SAXMachine
28
- element :title
29
- # the :as argument makes this available through atom_entry.author instead of .name
30
- element :name, :as => :author
31
- element "feedburner:origLink", :as => :url
32
- element :summary
33
- element :content, :class => AtomContent
34
- element :published
35
- ancestor :ancestor
36
- end
37
-
38
- # Class for parsing Atom feeds
39
- class Atom
40
- include SAXMachine
41
- element :title
42
- # the :with argument means that you only match a link tag that has an attribute of :type => "text/html"
43
- # the :value argument means that instead of setting the value to the text between the tag,
44
- # it sets it to the attribute value of :href
45
- element :link, :value => :href, :as => :url, :with => {:type => "text/html"}
46
- element :link, :value => :href, :as => :feed_url, :with => {:type => "application/atom+xml"}
47
- elements :entry, :as => :entries, :class => AtomEntry
48
- end
49
-
50
- # you can then parse like this
51
- feed = Atom.parse(xml_text)
52
- # then you're ready to rock
53
- feed.title # => whatever the title of the blog is
54
- feed.url # => the main url of the blog
55
- feed.feed_url # => goes to the feedburner feed
56
-
57
- feed.entries.first.title # => title of the first entry
58
- feed.entries.first.author # => the author of the first entry
59
- feed.entries.first.url # => the permalink on the blog for this entry
60
- feed.entries.first.ancestor # => the Atom ancestor
61
- # etc ...
62
-
63
- # you can also use the elements method without specifying a class like so
64
- class SomeServiceResponse
65
- include SAXMachine
66
- elements :message, :as => :messages
67
- end
68
-
69
- response = SomeServiceResponse.parse("<response><message>hi</message><message>world</message></response>")
70
- response.messages.first # => "hi"
71
- response.messages.last # => "world"
72
- </pre>
73
-
74
- # To limit conflicts in the class used for mappping, you can use the alternate SAXMachine.configure syntax
75
-
76
- class X < ActiveRecord::Base
77
-
78
- # this way no element, elements or ancestor method will be added to X
79
- SAXMachine.configure(X) do |c|
80
- c.element :title
81
- end
82
-
83
- end
84
-
85
- h2. LICENSE
86
-
87
- (The MIT License)
88
-
89
- Copyright (c) 2009 - 2011:
90
-
91
- "Paul Dix":http://pauldix.net
92
-
93
- Permission is hereby granted, free of charge, to any person obtaining
94
- a copy of this software and associated documentation files (the
95
- 'Software'), to deal in the Software without restriction, including
96
- without limitation the rights to use, copy, modify, merge, publish,
97
- distribute, sublicense, and/or sell copies of the Software, and to
98
- permit persons to whom the Software is furnished to do so, subject to
99
- the following conditions:
100
-
101
- The above copyright notice and this permission notice shall be
102
- included in all copies or substantial portions of the Software.
103
-
104
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
105
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
106
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
107
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
108
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
109
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
110
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,40 +0,0 @@
1
- module SAXMachine
2
- class SAXConfig
3
-
4
- class AttributeConfig
5
- attr_reader :name, :setter
6
-
7
- def initialize(name, options)
8
- @name = name.to_s
9
- @as = options[:as]
10
- @setter = "#{@as}="
11
- @required = options[:required]
12
- end
13
-
14
- def column
15
- @as || @name.to_sym
16
- end
17
-
18
- def required?
19
- @required
20
- end
21
-
22
- def value_from_attrs(attrs)
23
- attrs.index(@name) ? attrs[attrs.index(@name) + 1] : nil
24
- end
25
-
26
- def attrs_match?(attrs)
27
- attrs.index(@name) ? true : false
28
- end
29
-
30
- def has_value_and_attrs_match?(attrs)
31
- attrs_match?(attrs)
32
- end
33
-
34
- def collection?
35
- false
36
- end
37
- end
38
-
39
- end
40
- end
@@ -1,45 +0,0 @@
1
- module SAXMachine
2
- class SAXConfig
3
-
4
- class CollectionConfig
5
- attr_reader :name
6
-
7
- def initialize(name, options)
8
- @name = name.to_s
9
- @class = options[:class]
10
- @as = options[:as].to_s
11
-
12
- if options.has_key?(:with)
13
- # for faster comparisons later
14
- @with = options[:with].to_a.flatten.collect {|o| o.to_s}
15
- else
16
- @with = nil
17
- end
18
- end
19
-
20
- def accessor
21
- as
22
- end
23
-
24
- def attrs_match?(attrs)
25
- if @with
26
- @with == (@with & attrs)
27
- else
28
- true
29
- end
30
- end
31
-
32
- def data_class
33
- @class || @name
34
- end
35
-
36
- protected
37
-
38
- def as
39
- @as
40
- end
41
-
42
- end
43
-
44
- end
45
- end
@@ -1,107 +0,0 @@
1
- require "nokogiri"
2
-
3
- module SAXMachine
4
- class SAXHandler < Nokogiri::XML::SAX::Document
5
- attr_reader :stack
6
-
7
- def initialize(object, on_error = nil, on_warning = nil)
8
- @stack = [[object, nil, String.new]]
9
- @parsed_configs = {}
10
- @on_error = on_error
11
- @on_warning = on_warning
12
- end
13
-
14
- def characters(string)
15
- object, config, value = stack.last
16
- value << string
17
- end
18
-
19
- def cdata_block(string)
20
- characters(string)
21
- end
22
-
23
- def start_element(name, attrs = [])
24
- attrs.flatten!
25
- object, config, value = stack.last
26
- sax_config = object.class.respond_to?(:sax_config) ? object.class.sax_config : nil
27
-
28
- if sax_config
29
- if collection_config = sax_config.collection_config(name, attrs)
30
- stack.push [object = collection_config.data_class.new, collection_config, String.new]
31
- object, sax_config, is_collection = object, object.class.sax_config, true
32
-
33
- if (attribute_config = object.class.respond_to?(:sax_config) && object.class.sax_config.attribute_configs_for_element(attrs))
34
- attribute_config.each { |ac| object.send(ac.setter, ac.value_from_attrs(attrs)) }
35
- end
36
- end
37
- sax_config.element_configs_for_attribute(name, attrs).each do |ec|
38
- unless parsed_config?(object, ec)
39
- object.send(ec.setter, ec.value_from_attrs(attrs))
40
- mark_as_parsed(object, ec)
41
- end
42
- end
43
- if !collection_config && element_config = sax_config.element_config_for_tag(name, attrs)
44
- new_object = element_config.data_class ? element_config.data_class.new : object
45
- stack.push [new_object, element_config, String.new]
46
-
47
- if (attribute_config = new_object.class.respond_to?(:sax_config) && new_object.class.sax_config.attribute_configs_for_element(attrs))
48
- attribute_config.each { |ac| new_object.send(ac.setter, ac.value_from_attrs(attrs)) }
49
- end
50
- end
51
- end
52
- end
53
-
54
- def end_element(name)
55
- (object, tag_config, _), (element, config, value) = stack[-2..-1]
56
- return unless stack.size > 1 && config && config.name.to_s == name.to_s
57
-
58
- unless parsed_config?(object, config)
59
- if (element_value_config = config.data_class.respond_to?(:sax_config) && config.data_class.sax_config.element_values_for_element)
60
- element_value_config.each { |evc| element.send(evc.setter, value) }
61
- end
62
-
63
- if config.respond_to?(:accessor)
64
- subconfig = element.class.sax_config if element.class.respond_to?(:sax_config)
65
- if econf = subconfig.element_config_for_tag(name, [])
66
- element.send(econf.setter, value) unless econf.value_configured?
67
- end
68
- object.send(config.accessor) << element
69
- else
70
- value = config.data_class ? element : value
71
- object.send(config.setter, value) unless value == ""
72
- mark_as_parsed(object, config)
73
- end
74
-
75
- # try to set the ancestor
76
- sax_config = element.class.respond_to?(:sax_config) ? element.class.sax_config : nil
77
- if sax_config
78
- sax_config.ancestors.each do |ancestor|
79
- element.send(ancestor.setter, object)
80
- end
81
- end
82
- end
83
- stack.pop
84
- end
85
-
86
- def mark_as_parsed(object, element_config)
87
- @parsed_configs[[object.object_id, element_config.object_id]] = true unless element_config.collection?
88
- end
89
-
90
- def parsed_config?(object, element_config)
91
- @parsed_configs[[object.object_id, element_config.object_id]]
92
- end
93
-
94
- def warning string
95
- if @on_warning
96
- @on_warning.call(string)
97
- end
98
- end
99
-
100
- def error string
101
- if @on_error
102
- @on_error.call(string)
103
- end
104
- end
105
-
106
- end
107
- end
@@ -1,53 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class A
4
-
5
- SAXMachine.configure(A) do |c|
6
- c.element :title
7
- end
8
-
9
- end
10
-
11
- class B < A
12
-
13
- SAXMachine.configure(B) do |c|
14
- c.element :b
15
- end
16
-
17
- end
18
-
19
- class C < B
20
-
21
- SAXMachine.configure(C) do |c|
22
- c.element :c
23
- end
24
-
25
- end
26
-
27
- describe "SAXMachine configure" do
28
- before do
29
- xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"
30
- @a = A.new
31
- @a.parse xml
32
- @b = B.new
33
- @b.parse xml
34
- @c = C.new
35
- @c.parse xml
36
- end
37
- it { @a.should be_a(A) }
38
- it { @a.should_not be_a(B) }
39
- it { @a.should be_a(SAXMachine) }
40
- it { @a.title.should == "Test" }
41
- it { @b.should be_a(A) }
42
- it { @b.should be_a(B) }
43
- it { @b.should be_a(SAXMachine) }
44
- it { @b.title.should == "Test" }
45
- it { @b.b.should == "Matched!" }
46
- it { @c.should be_a(A) }
47
- it { @c.should be_a(B) }
48
- it { @c.should be_a(C) }
49
- it { @c.should be_a(SAXMachine) }
50
- it { @c.title.should == "Test" }
51
- it { @c.b.should == "Matched!" }
52
- it { @c.c.should == "And Again" }
53
- end
@@ -1,42 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class A
4
- include SAXMachine
5
- element :title
6
- end
7
-
8
- class B < A
9
- element :b
10
- end
11
-
12
- class C < B
13
- element :c
14
- end
15
-
16
- describe "SAXMachine inheritance" do
17
- before do
18
- xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"
19
- @a = A.new
20
- @a.parse xml
21
- @b = B.new
22
- @b.parse xml
23
- @c = C.new
24
- @c.parse xml
25
- end
26
- it { @a.should be_a(A) }
27
- it { @a.should_not be_a(B) }
28
- it { @a.should be_a(SAXMachine) }
29
- it { @a.title.should == "Test" }
30
- it { @b.should be_a(A) }
31
- it { @b.should be_a(B) }
32
- it { @b.should be_a(SAXMachine) }
33
- it { @b.title.should == "Test" }
34
- it { @b.b.should == "Matched!" }
35
- it { @c.should be_a(A) }
36
- it { @c.should be_a(B) }
37
- it { @c.should be_a(C) }
38
- it { @c.should be_a(SAXMachine) }
39
- it { @c.title.should == "Test" }
40
- it { @c.b.should == "Matched!" }
41
- it { @c.c.should == "And Again" }
42
- end