cells 3.8.8 → 3.9.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 +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +5 -2
- data/CHANGES.textile +23 -15
- data/Gemfile +1 -1
- data/README.md +412 -0
- data/Rakefile +2 -2
- data/cells.gemspec +5 -6
- data/gemfiles/Gemfile.rails3-0 +2 -2
- data/gemfiles/Gemfile.rails3-1 +1 -1
- data/gemfiles/Gemfile.rails3-2 +1 -2
- data/gemfiles/Gemfile.rails4-0 +7 -0
- data/lib/cell.rb +27 -0
- data/lib/cell/base.rb +31 -18
- data/lib/cell/builder.rb +11 -10
- data/lib/cell/dsl.rb +7 -0
- data/lib/cell/rack.rb +5 -9
- data/lib/cell/rails.rb +19 -11
- data/lib/cell/rails/view_model.rb +115 -0
- data/lib/cell/rails3_0_strategy.rb +1 -1
- data/lib/cell/rails3_1_strategy.rb +1 -1
- data/lib/cell/rails4_0_strategy.rb +1 -2
- data/lib/cell/test_case.rb +11 -11
- data/lib/cells.rb +4 -3
- data/lib/cells/rails.rb +16 -3
- data/lib/cells/version.rb +1 -1
- data/test/app/cells/bassist_cell.rb +9 -1
- data/test/app/cells/rails_helper_api_test/bassist/edit.html.erb +3 -3
- data/test/app/cells/song/dashboard.haml +7 -0
- data/test/app/cells/song/details.html.haml +1 -0
- data/test/app/cells/song/info.html.haml +1 -0
- data/test/app/cells/song/lyrics.html.haml +6 -0
- data/test/app/cells/song/plays.haml +1 -0
- data/test/app/cells/song/show.html.haml +3 -0
- data/test/app/cells/song/title.html.haml +1 -0
- data/test/app/cells/view_model_test/comments/show.haml +7 -0
- data/test/cell_module_test.rb +39 -41
- data/test/cell_test.rb +28 -0
- data/test/dummy/app/views/musician/featured_with_block.html.erb +1 -1
- data/test/dummy/app/views/musician/title.erb +1 -0
- data/test/dummy/config/routes.rb +1 -0
- data/test/helper_test.rb +13 -10
- data/test/rails/caching_test.rb +75 -73
- data/test/rails/cells_test.rb +25 -23
- data/test/rails/integration_test.rb +80 -61
- data/test/rails/view_model_test.rb +119 -0
- data/test/rails_helper_api_test.rb +11 -13
- metadata +41 -61
- data/README.rdoc +0 -279
- data/about.yml +0 -7
- data/test/app/cells/producer/capture.html.erb +0 -1
- data/test/app/cells/producer/content_for.html.erb +0 -2
- data/test/rails/capture_test.rb +0 -70
data/test/rails/cells_test.rb
CHANGED
|
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
|
2
2
|
|
|
3
3
|
class RailsCellsTest < MiniTest::Spec
|
|
4
4
|
include Cell::TestCase::TestMethods
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def swap(object, new_values)
|
|
7
7
|
old_values = {}
|
|
8
8
|
new_values.each do |key, value|
|
|
@@ -15,7 +15,7 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
15
15
|
object.send :"#{key}=", value
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
describe "#render_state" do
|
|
20
20
|
it "work without args" do
|
|
21
21
|
BassistCell.class_eval do
|
|
@@ -25,7 +25,7 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
25
25
|
end
|
|
26
26
|
assert_equal "That's a D!", cell(:bassist).render_state(:listen)
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
it "accept state-args" do
|
|
30
30
|
BassistCell.class_eval do
|
|
31
31
|
def listen(args)
|
|
@@ -34,7 +34,7 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
34
34
|
end
|
|
35
35
|
assert_equal "D", cell(:bassist).render_state(:listen, :note => "D")
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
it "accept state-args with default parameters" do
|
|
39
39
|
BassistCell.class_eval do
|
|
40
40
|
def listen(first, second="D")
|
|
@@ -44,13 +44,13 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
44
44
|
assert_equal "AD", cell(:bassist).render_state(:listen, "A")
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
|
|
48
|
+
|
|
49
49
|
describe "A rails cell" do
|
|
50
50
|
it "respond to DEFAULT_VIEW_PATHS" do
|
|
51
51
|
assert_equal ["app/cells"], Cell::Rails::DEFAULT_VIEW_PATHS
|
|
52
52
|
end
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
it "respond to .setup_view_paths!" do
|
|
55
55
|
swap( Cell::Rails, :view_paths => []) do
|
|
56
56
|
Cell::Rails.setup_view_paths!
|
|
@@ -61,46 +61,46 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
it "respond to view_paths" do
|
|
66
66
|
assert_kind_of ActionView::PathSet, Cell::Rails.view_paths, "must be a PathSet for proper template caching/reloading (see issue#2)"
|
|
67
67
|
end
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
it "respond to view_paths=" do
|
|
70
70
|
swap( Cell::Rails, :view_paths => ['you', 'are', 'here']) do
|
|
71
71
|
assert_kind_of ActionView::PathSet, Cell::Rails.view_paths, "must not wipe out the PathSet"
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
it "respond to #request" do
|
|
76
76
|
assert_equal @request, cell(:bassist).request
|
|
77
77
|
end
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
it "respond to #config" do
|
|
80
80
|
assert_equal({}, cell(:bassist).config)
|
|
81
81
|
end
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
|
|
83
|
+
|
|
84
84
|
if Cell.rails3_0?
|
|
85
85
|
describe "invoking find_family_view_for_state" do
|
|
86
86
|
it "raise an error when a template is missing" do
|
|
87
87
|
assert_raises ActionView::MissingTemplate do
|
|
88
88
|
cell(:bassist).find_template("bassist/playyy")
|
|
89
89
|
end
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
#puts "format: #{cell(:bassist).find_template("bassist/play.js").formats.inspect}"
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
it "return play.html.erb" do
|
|
95
95
|
assert_equal "bassist/play", cell(:bassist).send(:find_family_view_for_state, :play).virtual_path
|
|
96
96
|
end
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
it "find inherited play.html.erb" do
|
|
99
99
|
assert_equal "bassist/play", cell(:bad_guitarist).send(:find_family_view_for_state, :play).virtual_path
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
describe "delegation" do
|
|
105
105
|
before do
|
|
106
106
|
@request.env["action_dispatch.request.request_parameters"] = {:song => "Creatures"}
|
|
@@ -108,25 +108,27 @@ class RailsCellsTest < MiniTest::Spec
|
|
|
108
108
|
@controller.request = @request
|
|
109
109
|
@cell = cell(:bassist)
|
|
110
110
|
end
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
it "delegate log" do
|
|
113
113
|
skip
|
|
114
114
|
assert_nothing_raised do
|
|
115
115
|
cell(:bassist).class.logger.info("everything is perfect!")
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
it "respond to session" do
|
|
120
|
-
|
|
120
|
+
session_kind = Hash
|
|
121
|
+
session_kind = ActionController::TestSession if Cell.rails4_0_or_more?
|
|
122
|
+
assert_kind_of session_kind, @cell.session
|
|
121
123
|
end
|
|
122
|
-
|
|
124
|
+
|
|
123
125
|
it "respond to #params and return the request parameters" do
|
|
124
126
|
assert_equal({"song" => "Creatures"}, cell(:bassist).params)
|
|
125
127
|
end
|
|
126
|
-
|
|
128
|
+
|
|
127
129
|
it "not merge #params and #options" do
|
|
128
130
|
assert_equal({"song" => "Creatures"}, cell(:bassist, "song" => "Lockdown").params)
|
|
129
131
|
end
|
|
130
132
|
end
|
|
131
|
-
end
|
|
133
|
+
end
|
|
132
134
|
end
|
|
@@ -1,76 +1,95 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
|
-
class
|
|
3
|
+
class ControllerMethodsTest < ActionController::TestCase
|
|
4
4
|
tests MusicianController
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@controller.instance_eval do
|
|
20
|
-
def promotion
|
|
21
|
-
render :text => render_cell(:bassist, :enjoy, "The Stranglers", "my room")
|
|
22
|
-
end
|
|
5
|
+
|
|
6
|
+
class SongCell < Cell::Rails
|
|
7
|
+
include Cell::OptionsConstructor
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
test "#render_cell" do
|
|
11
|
+
get 'promotion'
|
|
12
|
+
assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />", @response.body
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "#render_cell with arbitrary options" do
|
|
16
|
+
BassistCell.class_eval do
|
|
17
|
+
def enjoy(what, where="the bar")
|
|
18
|
+
render :text => "I like #{what} in #{where}."
|
|
23
19
|
end
|
|
24
|
-
get 'promotion'
|
|
25
|
-
assert_equal "I like The Stranglers in my room.", @response.body
|
|
26
20
|
end
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
assert_equal BassistCell, @controller.flag
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "respond to render_cell in the view without escaping twice" do
|
|
35
|
-
BassistCell.class_eval do
|
|
36
|
-
def provoke; render; end
|
|
21
|
+
|
|
22
|
+
@controller.instance_eval do
|
|
23
|
+
def promotion
|
|
24
|
+
render :text => render_cell(:bassist, :enjoy, "The Stranglers", "my room")
|
|
37
25
|
end
|
|
38
|
-
get 'featured'
|
|
39
|
-
assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />", @response.body
|
|
40
26
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
27
|
+
get 'promotion'
|
|
28
|
+
assert_equal "I like The Stranglers in my room.", @response.body
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test "#render_cell with block" do
|
|
32
|
+
get 'promotion_with_block'
|
|
33
|
+
assert_equal "Doo", @response.body
|
|
34
|
+
assert_equal BassistCell, @controller.flag
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test "#cell_for" do
|
|
38
|
+
@controller.cell_for(:bassist).must_be_instance_of BassistCell
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test "#cell_for with options" do
|
|
42
|
+
@controller.cell_for("controller_methods_test/song", :title => "We Called It America").
|
|
43
|
+
title.must_equal "We Called It America"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ViewMethodsTest < ActionController::TestCase
|
|
49
|
+
tests MusicianController
|
|
50
|
+
|
|
51
|
+
test "#cell_for" do
|
|
52
|
+
@controller.instance_eval do
|
|
53
|
+
def title
|
|
50
54
|
end
|
|
51
|
-
get 'hamlet'
|
|
52
|
-
assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />\n", @response.body
|
|
53
55
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
|
|
57
|
+
get :title
|
|
58
|
+
@response.body.must_equal "First Call"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
test "#render_cell" do
|
|
62
|
+
get 'featured'
|
|
63
|
+
assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />", @response.body
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
test "#render_cell with a block" do
|
|
67
|
+
get 'featured_with_block'
|
|
68
|
+
assert_equal "Boing in D from BassistCell\n", @response.body
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
test "#render_cell in a haml view" do
|
|
72
|
+
get 'hamlet'
|
|
73
|
+
assert_equal "That's me, naked <img alt=\"Me\" src=\"/images/me.png\" />\n", @response.body
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
test "make params (and friends) available in a cell" do
|
|
77
|
+
BassistCell.class_eval do
|
|
78
|
+
def listen
|
|
79
|
+
render :text => "That's a #{params[:note]}"
|
|
60
80
|
end
|
|
61
|
-
get 'skills', :note => "D"
|
|
62
|
-
assert_equal "That's a D", @response.body
|
|
63
81
|
end
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
get 'skills', :note => "D"
|
|
83
|
+
assert_equal "That's a D", @response.body
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
test "respond to #config" do
|
|
87
|
+
BassistCell.class_eval do
|
|
88
|
+
def listen
|
|
89
|
+
render :view => 'contact_form' # form_tag internally calls config.allow_forgery_protection
|
|
70
90
|
end
|
|
71
|
-
get 'skills'
|
|
72
|
-
assert_equal "<form accept-charset=\"UTF-8\" action=\"musician/index\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /></div>\n", @response.body
|
|
73
91
|
end
|
|
92
|
+
get 'skills'
|
|
93
|
+
assert_equal "<form accept-charset=\"UTF-8\" action=\"musician/index\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /></div>\n", @response.body
|
|
74
94
|
end
|
|
75
|
-
|
|
76
95
|
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'cell/rails/view_model'
|
|
3
|
+
|
|
4
|
+
class Song < OpenStruct
|
|
5
|
+
extend ActiveModel::Naming
|
|
6
|
+
|
|
7
|
+
def persisted?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_param
|
|
12
|
+
id
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SongCell < Cell::Rails
|
|
19
|
+
include Cell::Rails::ViewModel
|
|
20
|
+
|
|
21
|
+
def show
|
|
22
|
+
render
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def title
|
|
26
|
+
song.title.upcase
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self_url
|
|
30
|
+
url_for(song)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def details
|
|
34
|
+
render
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def stats
|
|
38
|
+
render :details
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def info
|
|
42
|
+
render :info
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def dashboard
|
|
46
|
+
render :dashboard
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Lyrics < self
|
|
50
|
+
def show
|
|
51
|
+
render :lyrics
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class PlaysCell < self
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class ViewModelTest < MiniTest::Spec
|
|
60
|
+
# views :show, :create #=> wrap in render_state(:show, *)
|
|
61
|
+
let (:cell) { SongCell.build_for(nil, :title => "Shades Of Truth") }
|
|
62
|
+
|
|
63
|
+
it { cell.title.must_equal "Shades Of Truth" }
|
|
64
|
+
|
|
65
|
+
class HitCell < Cell::Base
|
|
66
|
+
include Cell::Rails::ViewModel
|
|
67
|
+
property :title
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
let (:song) { Song.new(:title => "65") }
|
|
71
|
+
it { HitCell.new(song).title.must_equal "65" }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if Cell.rails3_2_or_more?
|
|
75
|
+
class ViewModelIntegrationTest < ActionController::TestCase
|
|
76
|
+
tests MusicianController
|
|
77
|
+
|
|
78
|
+
#let (:song) { Song.new(:title => "Blindfold", :id => 1) }
|
|
79
|
+
#let (:html) { %{<h1>Shades Of Truth</h1>\n} }
|
|
80
|
+
#let (:cell) { }
|
|
81
|
+
|
|
82
|
+
setup do
|
|
83
|
+
@cell = SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => 1))
|
|
84
|
+
|
|
85
|
+
@url = "/songs/1"
|
|
86
|
+
@url = "http://test.host/songs/1" if Cell.rails4_0_or_more?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
test "URL helpers in view" do
|
|
91
|
+
@cell.show.must_equal %{<h1>BLINDFOLD</h1>
|
|
92
|
+
<a href=\"#{@url}\">Permalink</a>
|
|
93
|
+
} end
|
|
94
|
+
|
|
95
|
+
test "URL helper in instance" do
|
|
96
|
+
@cell.self_url.must_equal @url
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
test "implicit #render" do
|
|
100
|
+
@cell.details.must_equal "<h3>BLINDFOLD</h3>\n"
|
|
101
|
+
SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => 1)).details
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
test "explicit #render with one arg" do
|
|
105
|
+
@cell = SongCell.build_for(@controller, :song => Song.new(:title => "Blindfold", :id => 1))
|
|
106
|
+
@cell.stats.must_equal "<h3>BLINDFOLD</h3>\n"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
test "nested render" do
|
|
110
|
+
@cell.info.must_equal "<li>BLINDFOLD\n</li>\n"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
test "nested rendering method" do
|
|
114
|
+
@cell.dashboard.must_equal "<h1>Dashboard</h1>\n<h3>Lyrics for BLINDFOLD</h3>\n<li>\nIn the Mirror\n</li>\n<li>\nI can see\n</li>\n\nPlays: 99\n\nPlays: 99\n\n"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# TODO: when we don't pass :song into Lyrics
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -6,15 +6,15 @@ class RailsHelperAPITest < MiniTest::Spec
|
|
|
6
6
|
class ::Fruit
|
|
7
7
|
extend ActiveModel::Naming
|
|
8
8
|
include ActiveModel::Conversion
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def initialize(attributes={})
|
|
11
11
|
@attributes = attributes
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def title
|
|
15
15
|
@attributes[:title]
|
|
16
16
|
end
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
def persisted?
|
|
19
19
|
false
|
|
20
20
|
end
|
|
@@ -32,28 +32,26 @@ class RailsHelperAPITest < MiniTest::Spec
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
require "simple_form"
|
|
36
35
|
class BassistCell < Cell::Base
|
|
37
36
|
include Cell::Rails::HelperAPI
|
|
38
|
-
|
|
37
|
+
|
|
39
38
|
self._helpers = FakeHelpers
|
|
40
39
|
self._routes = FakeUrlFor.new
|
|
41
|
-
|
|
40
|
+
|
|
42
41
|
def edit
|
|
43
42
|
@tone = "C"
|
|
44
43
|
@fruit = Fruit.new(:title => "Banana")
|
|
45
44
|
render
|
|
46
45
|
end
|
|
47
46
|
end
|
|
48
|
-
|
|
47
|
+
|
|
49
48
|
describe "Rails::HelperAPI" do
|
|
50
49
|
it "allows accessing the request object" do
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
', BassistCell.new.render_state(:edit) if Cell.rails3_1_or_more? and Rails::VERSION::MINOR == 2
|
|
50
|
+
skip unless Cell.rails3_1_or_more? and Rails::VERSION::MINOR == 2
|
|
51
|
+
|
|
52
|
+
form = BassistCell.new.render_state(:edit)
|
|
53
|
+
form.must_match /<form accept-charset="UTF-8" action="\/fruits"/
|
|
54
|
+
form.must_match /name="fruit\[title\]"/
|
|
57
55
|
end
|
|
58
56
|
end
|
|
59
57
|
end
|