cells 3.5.0 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,11 @@
1
+ h2. 3.5.1
2
+ * No longer pass an explicit Proc but a versioner block to @Cell.Base.cache@. Example: @cache :show do "v1" end@
3
+ * Caching.cache_key_for now uses @ActiveSupport::Cache.expand_cache_key@. Consequently, a key which used to be like @"cells/director/count/a=1/b=2"@ now is @cells/director/count/a=1&b=2@ and so on. Be warned that this might break your home-made cache expiry.
4
+ * Controller#expire_cell_state now expects the cell class as first arg. Example: @expire_cell_state(DirectorCell, :count)@
5
+
6
+ h3. Bugfixes
7
+ * Passing options to @render :state@ in views finally works: @render({:state => :list_item}, item, i)@
8
+
1
9
  h2. 3.5.0
2
10
 
3
11
  h3. Changes
@@ -12,14 +12,14 @@ Gem::Specification.new do |s|
12
12
  s.email = ["apotonick@gmail.com"]
13
13
  s.homepage = "http://cells.rubyforge.org"
14
14
  s.summary = %q{View Components for Rails.}
15
- s.description = %q{Cells are View Components for Rails. They are lightweight controllers, can be rendered in views and thus provide an elegant and fast way for encapsulation and component-orientation.}
15
+ s.description = %q{Cells are view components for Rails. They are lightweight controllers, can be rendered in views and thus provide an elegant and fast way for encapsulation and component-orientation.}
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
- s.add_dependency "rails", "~> 3.0"
22
+ s.add_dependency "rails", "~> 3.0.0"
23
23
 
24
24
  s.add_development_dependency "shoulda"
25
25
  s.add_development_dependency "haml"
@@ -6,59 +6,42 @@ module Cell
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  module ClassMethods
9
- # Activate caching for the state <tt>state</tt>. If no other options are passed
10
- # the view will be cached forever.
9
+ # Caches the rendered view of +state+.
11
10
  #
12
- # You may pass a Proc or a Symbol as cache expiration <tt>version_proc</tt>.
13
- # This method is called every time the state is rendered, and is expected to return a
14
- # Hash containing the cache key ingredients.
11
+ # Examples:
15
12
  #
16
- # Additional options will be passed directly to the cache store when caching the state.
17
- # Useful for simply setting a TTL for a cached state.
18
- # Note that you may omit the <tt>version_proc</tt>.
13
+ # This will cache forever.
19
14
  #
15
+ # class CartCell < Cell::Base
16
+ # cache :show
20
17
  #
21
- # Example:
22
- # class CachingCell < ::Cell::Base
23
- # cache :versioned_cached_state, Proc.new{ {:version => 0} }
24
- # would result in the complete cache key
25
- # cells/CachingCell/versioned_cached_state/version=0
18
+ # You can also pass options to the caching engine as known from Rails caching.
26
19
  #
27
- # If you provide a symbol, you can access the cell instance directly in the versioning
28
- # method:
20
+ # cache :show, :expires_in => 10.minutes
29
21
  #
30
- # class CachingCell < ::Cell::Base
31
- # cache :cached_state, :my_cache_version
22
+ # If you need your own granular cache keys, pass a versioner block.
32
23
  #
33
- # def my_cache_version
34
- # { :user => current_user.id,
35
- # :item_id => params[:item] }
36
- # }
37
- # end
38
- # results in a very specific cache key, for customized caching:
39
- # cells/CachingCell/cached_state/user=18/item_id=1
24
+ # cache :show do |cell|
25
+ # "user/#{cell.options[:id]}"
26
+ # end
40
27
  #
41
- # You may also set a TTL only, e.g. when using the memcached store:
28
+ # This will result in a cache key like <tt>cells/cart/show/user/1</tt>.
42
29
  #
43
- # cache :cached_state, :expires_in => 3.minutes
30
+ # Alternatively, use an instance method.
44
31
  #
45
- # Or use both, having a versioning proc <em>and</em> a TTL expiring the state as a fallback
46
- # after a certain amount of time.
32
+ # cache :show, :versioner
33
+ # def versioner
34
+ # "user/#{options[:id]}"
35
+ # end
47
36
  #
48
- # cache :cached_state, Proc.new { {:version => 0} }, :expires_in => 10.minutes
49
- #--
50
- ### TODO: implement for string, nil.
51
- ### DISCUSS: introduce return method #sweep ? so the Proc can explicitly
52
- ### delegate re-rendering to the outside.
53
- #--
54
- def cache(state, version_proc=nil, cache_opts={})
55
- if version_proc.is_a?(Hash)
56
- cache_opts = version_proc
57
- version_proc = nil
58
- end
59
-
60
- version_procs[state] = version_proc
61
- cache_options[state] = cache_opts
37
+ # Two things to mention here.
38
+ # * The return value of the method/block is <em>appended</em> to the state cache key.
39
+ # * You may return a string, a hash, an array, ActiveSupport::Caching will compile it.
40
+ def cache(state, *args, &block)
41
+ options = args.extract_options!
42
+
43
+ version_procs[state] = args.first || block
44
+ cache_options[state] = options
62
45
  end
63
46
 
64
47
  def version_procs
@@ -69,55 +52,55 @@ module Cell
69
52
  @cache_options ||= {}
70
53
  end
71
54
 
72
- def cache_store #:nodoc:
55
+ def cache_store
56
+ # DISCUSS: move to instance level and delegate to #config/#parent_controller.
57
+ # This would allow convenient cache settings per cell (if needed).
73
58
  ::ActionController::Base.cache_store
74
59
  end
75
-
76
- def cache_key_for(cell_class, state, args = {}) #:nodoc:
77
- key_pieces = [cell_class, state]
78
-
79
- args.collect{|a,b| [a.to_s, b]}.sort.each{ |k,v| key_pieces << "#{k}=#{v}" }
80
- key = key_pieces.join('/')
81
-
82
- ::ActiveSupport::Cache.expand_cache_key(key, :cells)
60
+
61
+ # Computes the complete, namespaced cache key for +state+.
62
+ def state_cache_key(state, key_parts={})
63
+ expand_cache_key([cell_name, state, key_parts])
83
64
  end
84
65
 
85
- def expire_cache_key(key, opts=nil)
86
- cache_store.delete(key, opts)
66
+ def expire_cache_key(key, *args)
67
+ cache_store.delete(key, *args)
87
68
  end
88
-
89
- def cache_configured?
90
- ::ActionController::Base.cache_configured?
69
+
70
+ def cache?(state)
71
+ # DISCUSS: why is it private?
72
+ ActionController::Base.send(:cache_configured?) and state_cached?(state)
73
+ end
74
+
75
+ protected
76
+ # Compiles cache key and adds :cells namespace to +key+, according to the
77
+ # ActiveSupport::Cache.expand_cache_key API.
78
+ def expand_cache_key(key)
79
+ ::ActiveSupport::Cache.expand_cache_key(key, :cells)
80
+ end
81
+
82
+ def state_cached?(state)
83
+ version_procs.has_key?(state)
91
84
  end
92
85
  end
93
86
 
94
87
  def render_state(state, *args)
95
- return super(state, *args) unless state_cached?(state)
96
-
97
- key = cache_key(state, call_version_proc_for_state(state))
88
+ return super(state, *args) unless self.class.cache?(state)
89
+
90
+ key = self.class.state_cache_key(state, call_state_versioner(state))
98
91
  options = self.class.cache_options[state]
99
-
92
+
100
93
  self.class.cache_store.fetch(key, options) do
101
94
  super(state, *args)
102
95
  end
103
96
  end
104
-
105
- # Call the versioning Proc for the respective state.
106
- def call_version_proc_for_state(state)
107
- version_proc = self.class.version_procs[state]
108
-
109
- return {} unless version_proc # call to #cache was without any args.
110
-
97
+
98
+ def call_state_versioner(state)
99
+ version_proc = self.class.version_procs[state] or return
100
+
111
101
  return version_proc.call(self) if version_proc.kind_of?(Proc)
112
102
  send(version_proc)
113
103
  end
114
-
115
- def cache_key(state, args = {}) #:nodoc:
116
- self.class.cache_key_for(self.class.cell_name, state, args)
117
- end
118
-
119
- def state_cached?(state)
120
- self.class.version_procs.has_key?(state)
121
- end
104
+
122
105
  end
123
106
  end
@@ -10,11 +10,10 @@ module Cell
10
10
 
11
11
 
12
12
  class View < ActionView::Base
13
- def render(options = {}, locals = {}, &block)
14
- if options[:state] or options[:view]
15
- return @_controller.render(options, &block)
16
- end
17
-
13
+ def render(*args, &block)
14
+ options = args.first.is_a?(::Hash) ? args.first : {} # this is copied from #render by intention.
15
+
16
+ return controller.render(*args, &block) if options[:state] or options[:view]
18
17
  super
19
18
  end
20
19
  end
@@ -36,9 +36,14 @@ module Cells
36
36
  # end
37
37
  #
38
38
  # will expire the view for state <tt>:display_list</tt> in the cell <tt>MyListingCell</tt>.
39
- def expire_cell_state(cell_name, state, args={}, opts=nil)
40
- key = ::Cell::Base.cache_key_for(cell_name, state, args)
41
- ::Cell::Base.expire_cache_key(key, opts)
39
+ def expire_cell_state(cell_class, state, args={}, opts=nil)
40
+ if cell_class.is_a?(Symbol)
41
+ ActiveSupport::Deprecation.warn "Please pass the cell class into #expire_cell_state, as in expire_cell_state(DirectorCell, :count, :user_id => 1)"
42
+ cell_class = Cell::Base.class_from_cell_name(cell_class)
43
+ end
44
+
45
+ key = cell_class.state_cache_key(state, args)
46
+ cell_class.expire_cache_key(key, opts)
42
47
  end
43
48
  end
44
49
 
@@ -1,3 +1,3 @@
1
1
  module Cells
2
- VERSION = '3.5.0'
2
+ VERSION = '3.5.1'
3
3
  end
@@ -1,203 +1,272 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DirectorCell < Cell::Rails
4
- cache :count
4
+ attr_reader :count
5
5
 
6
- @@counter = 0
7
- cattr_accessor :counter
6
+ def initialize(*)
7
+ super
8
+ @count = 0
9
+ end
8
10
 
9
- def self.increment!
10
- @@counter += 1
11
+ cache :tock
12
+ def tock
13
+ @count += 1
14
+ render :text => @count
11
15
  end
16
+ end
17
+
18
+ class CachingUnitTest < ActiveSupport::TestCase
19
+ include Cell::TestCase::TestMethods
12
20
 
13
- def self.reset!
14
- @@counter = 0
21
+ setup do
22
+ ActionController::Base.cache_store.clear
23
+ ActionController::Base.perform_caching = true
24
+ @cell = cell(:director)
25
+ @class = @cell.class
15
26
  end
16
27
 
17
- def increment!
18
- self.class.increment!
28
+
29
+ context ".state_cache_key" do
30
+ should "accept state only" do
31
+ assert_equal "cells/director/count/", @class.state_cache_key(:count)
32
+ end
33
+
34
+ should "accept hash as key parts" do
35
+ assert_equal "cells/director/count/a=1&b=2", @class.state_cache_key(:count, :b=>2, :a=>1)
36
+ end
37
+
38
+ should "accept array as key parts" do
39
+ assert_equal "cells/director/count/1/2/3", @class.state_cache_key(:count, [1,2,3])
40
+ end
41
+
42
+ should "accept string as key parts" do
43
+ assert_equal "cells/director/count/1/2", @class.state_cache_key(:count, "1/2")
44
+ end
45
+
46
+ should "accept nil as key parts" do
47
+ assert_equal "cells/director/count/", @class.state_cache_key(:count, nil)
48
+ end
19
49
  end
20
50
 
21
- def count
22
- render :text => increment!
23
- end
24
- end
25
-
26
- class CachingTest < ActiveSupport::TestCase
27
- include Cell::TestCase::TestMethods
28
51
 
29
- context "The DirectorCell" do
30
- setup do
31
- DirectorCell.reset!
52
+ context ".expand_cache_key" do
53
+ should "add :cells namespace" do
54
+ assert_equal "cells/director/count", @class.send(:expand_cache_key, [:director, :count])
55
+ end
56
+ end
57
+
58
+
59
+ context ".state_cached?" do
60
+ should "return true for cached" do
61
+ assert @class.send :state_cached?, :count
32
62
  end
33
63
 
34
- should "respond to #increment" do
35
- assert_equal 0, DirectorCell.counter
36
- assert_equal 1, DirectorCell.increment!
37
- assert_equal 1, DirectorCell.counter
64
+ should "return false otherwise" do
65
+ assert_not @class.send :state_cached?, :sing
38
66
  end
39
67
  end
40
68
 
41
- context "A cell" do
42
- setup do
43
- ::ActionController::Base.cache_store = :memory_store
44
- ::ActionController::Base.perform_caching = true
45
- DirectorCell.reset!
69
+
70
+ context ".cache?" do
71
+ should "return true for cached" do
72
+ assert @cell.class.cache?(:count)
46
73
  end
47
74
 
48
- should "respond to state_cached?" do
49
- assert cell(:director).state_cached?(:count)
50
- assert_not cell(:director).state_cached?(:sing)
75
+ should "return false otherwise" do
76
+ assert_not @cell.class.cache?(:sing)
51
77
  end
52
78
 
53
- context "caching a state" do
54
- setup do
55
- @proc = Proc.new{}
79
+ context "perform_caching turned off" do
80
+ teardown do
81
+ ::ActionController::Base.perform_caching = true
56
82
  end
57
83
 
58
- should "save the version proc" do
59
- DirectorCell.cache :count, @proc
60
-
61
- assert_equal @proc, cell(:director).class.version_procs[:count]
62
- assert_equal({}, cell(:director).class.cache_options[:count])
84
+ should "always return false if caching turned-off" do
85
+ ::ActionController::Base.perform_caching = false
86
+ assert_not @cell.class.cache?(:count)
87
+ assert_not @cell.class.cache?(:sing)
63
88
  end
64
-
65
- should "save the cache options" do
66
- DirectorCell.cache :count, @proc, :expires_in => 10.minutes
67
-
68
- assert_equal @proc, cell(:director).class.version_procs[:count]
69
- assert_equal({:expires_in => 10.minutes}, cell(:director).class.cache_options[:count])
89
+ end
90
+ end
91
+
92
+
93
+ context ".expire_cache_key" do
94
+ setup do
95
+ @key = @class.state_cache_key(:tock)
96
+ assert_equal "1", render_cell(:director, :tock)
97
+ assert_equal "1", @class.cache_store.read(@key)
98
+ end
99
+
100
+ should "delete the state from cache" do
101
+ @class.expire_cache_key(@key)
102
+ assert_not @class.cache_store.read(@key)
103
+ end
104
+
105
+ should "be available in controllers for sweepers" do
106
+ MusicianController.new.expire_cell_state(DirectorCell, :tock)
107
+ assert_not @class.cache_store.read(@key)
108
+ end
109
+
110
+ should "accept cache options" do
111
+ key = @class.state_cache_key(:tock, :volume => 9)
112
+ assert Cell::Base.cache_store.write(key, 'ONE!')
113
+
114
+ MusicianController.new.expire_cell_state(DirectorCell, :tock, :volume => 9)
115
+ assert_equal "1", @class.cache_store.read(@key)
116
+ assert_not ::Cell::Base.cache_store.read(key)
117
+ end
118
+
119
+ should "raise a deprecation notice when passing in a :symbol" do
120
+ assert_deprecated do
121
+ MusicianController.new.expire_cell_state(:director, :tock)
70
122
  end
123
+ assert_not @class.cache_store.read(@key)
124
+ end
125
+ end
126
+
127
+
128
+ context ".cache" do
129
+ setup do
130
+ @proc = Proc.new{}
131
+ end
132
+
133
+ should "accept a state name, only" do
134
+ @class.cache :count
71
135
 
72
- should "not mix caching configuration with other classes" do
73
- DirectorCell.cache :count
74
- class SecondDirectorCell < DirectorCell; end
75
- SecondDirectorCell.cache :count, @proc
76
-
77
- assert_equal nil, cell(:director).class.version_procs[:count]
78
- assert_equal @proc, cell(:"caching_test/second_director").class.version_procs[:count]
79
- end
136
+ assert_not @class.version_procs[:count]
137
+ assert_equal({}, @class.cache_options[:count])
80
138
  end
81
139
 
82
- context "caching without options" do
83
- setup do
84
- key = cell(:director).cache_key(:count, :count => 0)
85
- Cell::Base.expire_cache_key(key) ### TODO: separate test
86
- end
140
+ should "accept state and cache options" do
141
+ @class.cache :count, :expires_in => 10.minutes
87
142
 
88
- should "cache forever" do
89
- DirectorCell.class_eval do
90
- cache :count
91
- end
92
-
93
- assert cell(:director).state_cached?(:count)
94
- assert_equal nil, cell(:director).class.version_procs[:count]
95
- assert_equal({}, cell(:director).class.cache_options[:count])
96
-
97
- assert_equal render_cell(:director, :count), render_cell(:director, :count)
98
- end
143
+ assert_not @class.version_procs[:count]
144
+ assert_equal({:expires_in => 10.minutes}, @class.cache_options[:count])
145
+ end
146
+
147
+ should "accept args and versioner block" do
148
+ @class.cache :count, :expires_in => 10.minutes do "v1" end
149
+
150
+ assert_kind_of Proc, @class.version_procs[:count]
151
+ assert_equal({:expires_in => 10.minutes}, @class.cache_options[:count])
152
+ end
153
+
154
+ should "stil accept a versioner proc, only" do
155
+ @class.cache :count, @proc
99
156
 
100
- should "not cache at all" do
101
- DirectorCell.class_eval do
102
- def dictate
103
- render :text => increment!
104
- end
105
- end
106
-
107
- assert_equal "1", render_cell(:director, :dictate)
108
- assert_equal "2", render_cell(:director, :dictate)
109
- end
157
+ assert_equal @proc, @class.version_procs[:count]
158
+ assert_equal({}, @class.cache_options[:count])
159
+ end
160
+
161
+ should "stil accept a versioner block" do
162
+ @class.cache :count do "v1" end
110
163
 
111
- should "expire the cache with a version proc" do
112
- DirectorCell.class_eval do
113
- cache :count, Proc.new { |cell|
114
- cell.class.counter >= 2 ? {:count => 2} : {:count => 0}
115
- }
116
-
117
- def count
118
- render :text => increment!
119
- end
120
- end
121
- DirectorCell.reset!
122
-
123
- assert_equal "1", render_cell(:director, :count)
124
- assert_equal "1", render_cell(:director, :count) # cached.
125
-
126
- DirectorCell.counter = 2 # invalidates the view cache.
127
- assert_equal "3", render_cell(:director, :count)
128
- assert_equal "3", render_cell(:director, :count) # cached.
129
- end
164
+ assert_kind_of Proc, @class.version_procs[:count]
165
+ assert_equal({}, @class.cache_options[:count])
166
+ end
167
+
168
+ should "not inherit caching configuration" do
169
+ @class.cache :count
170
+ klass = Class.new(@class)
171
+ klass.cache :count, @proc
130
172
 
131
- should "expire the cache with an instance method" do
132
- DirectorCell.class_eval do
133
- cache :count, :expire_count
134
-
135
- def expire_count
136
- self.class.counter >= 2 ? {:count => 2} : {:count => 0}
137
- end
138
-
139
- def count
140
- render :text => increment!
141
- end
142
- end
143
- DirectorCell.reset!
144
-
145
- assert_equal "1", render_cell(:director, :count)
146
- assert_equal "1", render_cell(:director, :count) # cached.
147
-
148
- DirectorCell.counter = 2 # invalidates the view cache.
149
- assert_equal "3", render_cell(:director, :count)
150
- assert_equal "3", render_cell(:director, :count) # cached.
151
- end
173
+ assert_not cell(:director).class.version_procs[:count]
174
+ assert_equal @proc, klass.version_procs[:count]
152
175
  end
153
176
  end
177
+ end
154
178
 
155
- context "cache_key" do
156
- setup do
157
- @cell = cell(:director)
158
- end
179
+ class CachingFunctionalTest < ActiveSupport::TestCase
180
+ include Cell::TestCase::TestMethods
181
+
182
+ setup do
183
+ ActionController::Base.cache_store.clear
184
+ ActionController::Base.perform_caching = true
185
+ setup # from Cell::TestCase::TestMethods
159
186
 
160
- should "respond to cache_key" do
161
- assert_equal "cells/director/count", @cell.cache_key(:count)
162
- assert_equal @cell.cache_key(:count), ::Cell::Base.cache_key_for(:director, :count)
187
+ @cell = cell(:director)
188
+ @class = @cell.class
189
+ end
190
+
191
+ context "turned off" do
192
+ should "not invoke caching" do
193
+ ::ActionController::Base.perform_caching = false
194
+
195
+ assert_equal "1", @cell.render_state(:tock)
196
+ assert_equal "2", @cell.render_state(:tock)
163
197
  end
164
-
165
- should "order options lexically" do
166
- assert_equal "cells/director/count/a=1/b=2", @cell.cache_key(:count, :b => 2, :a => 1)
198
+ end
199
+
200
+
201
+ context "without options" do
202
+ should "cache forever" do
203
+ @class.cache :tock
204
+ assert_equal "1", render_cell(:director, :tock)
205
+ assert_equal "1", render_cell(:director, :tock)
167
206
  end
168
207
  end
169
208
 
170
- context "expire_cache_key" do
171
- setup do
172
- DirectorCell.class_eval do
173
- cache :count
174
- def count
175
- render :text => increment!
209
+
210
+ context "uncached states" do
211
+ should "not cache at all" do
212
+ @class.class_eval do
213
+ def dictate
214
+ @count ||= 0
215
+ render :text => (@count += 1)
176
216
  end
177
217
  end
178
- DirectorCell.reset!
179
218
 
180
- @key = cell(:director).cache_key(:count)
181
- render_cell(:director, :count)
182
- assert_equal "1", ::Cell::Base.cache_store.read(@key)
219
+ assert_equal "1", @cell.render_state(:dictate)
220
+ assert_equal "2", @cell.render_state(:dictate)
221
+ end
222
+ end
223
+
224
+ context "with versioner" do
225
+ setup do
226
+ @class.class_eval do
227
+ def count(i)
228
+ render :text => i
229
+ end
230
+ end
183
231
  end
184
232
 
185
- should "delete the view from cache" do
186
- ::Cell::Base.expire_cache_key(@key)
187
- assert_not ::Cell::Base.cache_store.read(@key)
233
+ should "compute the key with the proc" do
234
+ @class.cache :count do |cell|
235
+ (cell.options % 2)==0 ? {:count => "even"} : {:count => "odd"}
236
+ end
237
+ # example cache key: cells/director/count/count=odd
238
+
239
+ assert_equal "1", render_cell(:director, :count, 1)
240
+ assert_equal "2", render_cell(:director, :count, 2)
241
+ assert_equal "1", render_cell(:director, :count, 3)
242
+ assert_equal "2", render_cell(:director, :count, 4)
188
243
  end
189
244
 
190
- should "be available in controllers for sweepers" do
191
- MusicianController.new.expire_cell_state(:director, :count)
192
- assert_not ::Cell::Base.cache_store.read(@key)
245
+ should "compute the key with an instance method" do
246
+ @class.cache :count, :version
247
+ @class.class_eval do
248
+ def version
249
+ (options % 3)==0 ? {:count => "even"} : {:count => "odd"}
250
+ end
251
+ end
252
+
253
+ assert_equal "1", render_cell(:director, :count, 1)
254
+ assert_equal "1", render_cell(:director, :count, 2)
255
+ assert_equal "3", render_cell(:director, :count, 3)
256
+ assert_equal "1", render_cell(:director, :count, 4)
257
+ assert_equal "1", render_cell(:director, :count, 5)
258
+ assert_equal "3", render_cell(:director, :count, 6)
193
259
  end
194
260
 
195
- should "accept cache options" do
196
- key = cell(:director).cache_key(:count, :volume => 9)
197
- assert ::Cell::Base.cache_store.write(key, 'ONE!')
198
-
199
- MusicianController.new.expire_cell_state(:director, :count, :volume => 9)
200
- assert_not ::Cell::Base.cache_store.read(key)
261
+ should "allow returning strings, too" do
262
+ @class.cache :count do |cell|
263
+ (cell.options % 2)==0 ? "even" : "odd"
264
+ end
265
+
266
+ assert_equal "1", render_cell(:director, :count, 1)
267
+ assert_equal "2", render_cell(:director, :count, 2)
268
+ assert_equal "1", render_cell(:director, :count, 3)
269
+ assert_equal "2", render_cell(:director, :count, 4)
201
270
  end
202
271
  end
203
272
  end
@@ -18,5 +18,21 @@ class RailsViewTest < ActiveSupport::TestCase
18
18
  end
19
19
  end
20
20
 
21
+ should "respond to render :state" do
22
+ assert_equal("Doo", in_view(:bassist) do
23
+ render :state => :play
24
+ end)
25
+ end
26
+
27
+ should "respond to render :state with options" do
28
+ BassistCell.class_eval do
29
+ def listen(*args)
30
+ render :text => "Listening to #{args.join(' ')}"
31
+ end
32
+ end
33
+ assert_equal("Listening to Much the Same", in_view(:bassist) do
34
+ render({:state => :listen}, "Much", "the", "Same")
35
+ end)
36
+ end
21
37
  end
22
38
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 3
7
7
  - 5
8
- - 0
9
- version: 3.5.0
8
+ - 1
9
+ version: 3.5.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-02-05 00:00:00 +01:00
17
+ date: 2011-02-10 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -28,7 +28,8 @@ dependencies:
28
28
  segments:
29
29
  - 3
30
30
  - 0
31
- version: "3.0"
31
+ - 0
32
+ version: 3.0.0
32
33
  type: :runtime
33
34
  version_requirements: *id001
34
35
  - !ruby/object:Gem::Dependency
@@ -57,7 +58,7 @@ dependencies:
57
58
  version: "0"
58
59
  type: :development
59
60
  version_requirements: *id003
60
- description: Cells are View Components for Rails. They are lightweight controllers, can be rendered in views and thus provide an elegant and fast way for encapsulation and component-orientation.
61
+ description: Cells are view components for Rails. They are lightweight controllers, can be rendered in views and thus provide an elegant and fast way for encapsulation and component-orientation.
61
62
  email:
62
63
  - apotonick@gmail.com
63
64
  executables: []