cells 3.7.1 → 3.8.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.
- data/CHANGES.textile +11 -1
- data/README.rdoc +13 -0
- data/cells.gemspec +1 -0
- data/lib/cell.rb +0 -78
- data/lib/cell/base.rb +1 -1
- data/lib/cell/builder.rb +71 -0
- data/lib/cell/deprecations.rb +2 -1
- data/lib/cell/rails.rb +22 -123
- data/lib/cell/rendering.rb +109 -0
- data/lib/cell/test_case.rb +2 -2
- data/lib/cells.rb +1 -4
- data/lib/cells/rails.rb +3 -3
- data/lib/cells/railtie.rb +1 -1
- data/lib/cells/version.rb +1 -1
- data/test/app/cells/bassist_cell.rb +1 -1
- data/test/app/cells/club_security/guard_cell.rb +2 -2
- data/test/app/cells/club_security/medic_cell.rb +2 -2
- data/test/app/cells/shouter/sing.html.erb +1 -0
- data/test/cell_module_test.rb +48 -18
- data/test/cells_module_test.rb +3 -3
- data/test/deprecations_test.rb +2 -2
- data/test/helper_test.rb +1 -1
- data/test/rails/caching_test.rb +2 -2
- data/test/rails/cells_test.rb +6 -6
- data/test/test_case_test.rb +8 -2
- data/test/test_helper.rb +1 -0
- metadata +20 -5
- data/lib/cells/rails_compat.rb +0 -12
data/CHANGES.textile
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
+
h2. 3.8.0
|
2
|
+
|
3
|
+
* @Cell::Base@ got rid of the controller dependency. If you want the @ActionController@ instance around in your cell, use @Cell::Rails@ - this should be the default in a standard Rails setup. However, if you plan on using a Cell in a Rack middleware or don't need the controller, use @Cell::Base@.
|
4
|
+
* New API (note that @controller@ isn't the first argument anymore):
|
5
|
+
** @Rails.create_cell_for(name, controller)@
|
6
|
+
** @Rails.render_cell_for(name, state, controller, *args)@
|
7
|
+
* Moved builder methods to @Cell::Builder@ module.
|
8
|
+
* @DEFAULT_VIEW_PATHS@ is now in @Cell::Base@.
|
9
|
+
* Removed the monkey-patch that made state-args work in Rails <= 3.0.3. Upgrade to +3.0.4.
|
10
|
+
|
1
11
|
h2. 3.7.1
|
2
12
|
|
3
|
-
*
|
13
|
+
* Works with Rails 3.2, too. Hopefully.
|
4
14
|
|
5
15
|
h2. 3.7.0
|
6
16
|
|
data/README.rdoc
CHANGED
@@ -173,6 +173,19 @@ To run your specs we got a rake task, too!
|
|
173
173
|
$ rake spec:cells
|
174
174
|
|
175
175
|
|
176
|
+
== Mountable Cells
|
177
|
+
|
178
|
+
Cells 3.8 got rid of the ActionController dependency. This essentially means you can mount Cells to routes or use them like a Rack middleware. All you need to do is derive from @Cell::Base@.
|
179
|
+
|
180
|
+
class PostCell < Cell::Base
|
181
|
+
..
|
182
|
+
|
183
|
+
In your @routes.rb@ file, mount the cell like a Rack app.
|
184
|
+
|
185
|
+
match "/posts" => proc { |env|
|
186
|
+
[ 200, {}, [ Cell::Base.render_cell_for(:post, :show) ]]
|
187
|
+
}
|
188
|
+
|
176
189
|
== Rails 2.3 note
|
177
190
|
|
178
191
|
In order to copy the cells rake tasks to your app, run
|
data/cells.gemspec
CHANGED
data/lib/cell.rb
CHANGED
@@ -1,80 +1,2 @@
|
|
1
1
|
module Cell
|
2
|
-
autoload :Caching, 'cell/caching'
|
3
|
-
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
DEFAULT_VIEW_PATHS = [File.join('app', 'cells')]
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
# Called in Railtie at initialization time.
|
10
|
-
def setup_view_paths!
|
11
|
-
self.view_paths = self::DEFAULT_VIEW_PATHS
|
12
|
-
end
|
13
|
-
|
14
|
-
# Main entry point for #render_cell.
|
15
|
-
def render_cell_for(controller, name, state, *args)
|
16
|
-
cell = create_cell_for(controller, name, *args)
|
17
|
-
yield cell if block_given?
|
18
|
-
|
19
|
-
cell.render_state(state, *args)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Creates a cell instance. Note that this method calls builders which were attached to the
|
23
|
-
# class with Cell::Base.build - this might lead to a different cell being returned.
|
24
|
-
def create_cell_for(controller, name, *args)
|
25
|
-
class_from_cell_name(name).build_for(controller, *args)
|
26
|
-
end
|
27
|
-
|
28
|
-
def build_for(controller, *args)
|
29
|
-
build_class_for(controller, *args).
|
30
|
-
new(controller)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Adds a builder to the cell class. Builders are used in #render_cell to find out the concrete
|
34
|
-
# class for rendering. This is helpful if you frequently want to render subclasses according
|
35
|
-
# to different circumstances (e.g. login situations) and you don't want to place these deciders in
|
36
|
-
# your view code.
|
37
|
-
#
|
38
|
-
# Passes the opts hash from #render_cell into the block. The block is executed in controller context.
|
39
|
-
# Multiple build blocks are ORed, if no builder matches the building cell is used.
|
40
|
-
#
|
41
|
-
# Example:
|
42
|
-
#
|
43
|
-
# Consider two different user box cells in your app.
|
44
|
-
#
|
45
|
-
# class AuthorizedUserBox < UserInfoBox
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# class AdminUserBox < UserInfoBox
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# Now you don't want to have deciders all over your views - use a declarative builder.
|
52
|
-
#
|
53
|
-
# UserInfoBox.build do |opts|
|
54
|
-
# AuthorizedUserBox if user_signed_in?
|
55
|
-
# AdminUserBox if admin_signed_in?
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# In your view #render_cell will instantiate the right cell for you now.
|
59
|
-
def build(&block)
|
60
|
-
builders << block
|
61
|
-
end
|
62
|
-
|
63
|
-
# The cell class constant for +cell_name+.
|
64
|
-
def class_from_cell_name(cell_name)
|
65
|
-
"#{cell_name}_cell".classify.constantize
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
def build_class_for(controller, *args)
|
70
|
-
builders.each do |blk|
|
71
|
-
klass = controller.instance_exec(*args, &blk) and return klass
|
72
|
-
end
|
73
|
-
self
|
74
|
-
end
|
75
|
-
|
76
|
-
def builders
|
77
|
-
@builders ||= []
|
78
|
-
end
|
79
|
-
end
|
80
2
|
end
|
data/lib/cell/base.rb
CHANGED
data/lib/cell/builder.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Cell
|
2
|
+
# Contains all methods for dynamically building a cell instance by using decider blocks.
|
3
|
+
module Builder
|
4
|
+
# Creates a cell instance. Note that this method calls builders which were attached to the
|
5
|
+
# class with Cell::Base.build - this might lead to a different cell being returned.
|
6
|
+
def create_cell_for(name, *args)
|
7
|
+
class_from_cell_name(name).build_for(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_for(*args) # DISCUSS: remove?
|
11
|
+
build_class_for(*args).
|
12
|
+
create_cell(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Adds a builder to the cell class. Builders are used in #render_cell to find out the concrete
|
16
|
+
# class for rendering. This is helpful if you frequently want to render subclasses according
|
17
|
+
# to different circumstances (e.g. login situations) and you don't want to place these deciders in
|
18
|
+
# your view code.
|
19
|
+
#
|
20
|
+
# Passes the opts hash from #render_cell into the block. The block is executed in controller context.
|
21
|
+
# Multiple build blocks are ORed, if no builder matches the building cell is used.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
#
|
25
|
+
# Consider two different user box cells in your app.
|
26
|
+
#
|
27
|
+
# class AuthorizedUserBox < UserInfoBox
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# class AdminUserBox < UserInfoBox
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Now you don't want to have deciders all over your views - use a declarative builder.
|
34
|
+
#
|
35
|
+
# UserInfoBox.build do |opts|
|
36
|
+
# AuthorizedUserBox if user_signed_in?
|
37
|
+
# AdminUserBox if admin_signed_in?
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# In your view #render_cell will instantiate the right cell for you now.
|
41
|
+
def build(&block)
|
42
|
+
builders << block
|
43
|
+
end
|
44
|
+
|
45
|
+
# The cell class constant for +cell_name+.
|
46
|
+
def class_from_cell_name(cell_name)
|
47
|
+
"#{cell_name}_cell".classify.constantize
|
48
|
+
end
|
49
|
+
|
50
|
+
# Override this if you want to receive arguments right in the cell constructor.
|
51
|
+
def create_cell(*args)
|
52
|
+
new
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def build_class_for(*args)
|
57
|
+
builders.each do |blk|
|
58
|
+
klass = run_builder_block(blk, *args) and return klass
|
59
|
+
end
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_builder_block(block, *args)
|
64
|
+
block.call(*args)
|
65
|
+
end
|
66
|
+
|
67
|
+
def builders
|
68
|
+
@builders ||= []
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/cell/deprecations.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Cell
|
2
2
|
# Makes #options available in Cells 3.7, which was removed in favor of state-args.
|
3
|
+
# Note that Deprecations are only available for Cell::Rails.
|
3
4
|
module Deprecations
|
4
5
|
extend ActiveSupport::Concern
|
5
6
|
|
@@ -18,7 +19,7 @@ module Cell
|
|
18
19
|
|
19
20
|
module InstanceMethods
|
20
21
|
def initialize(parent_controller, *args)
|
21
|
-
super(parent_controller) # the real
|
22
|
+
super(parent_controller) # the real Rails.new.
|
22
23
|
setup_backwardibility(*args)
|
23
24
|
end
|
24
25
|
|
data/lib/cell/rails.rb
CHANGED
@@ -1,141 +1,40 @@
|
|
1
|
-
require '
|
2
|
-
require 'cell'
|
1
|
+
require 'cell/base'
|
3
2
|
|
4
3
|
module Cell
|
5
|
-
class Rails <
|
6
|
-
include Cell
|
7
|
-
include AbstractController
|
8
|
-
include Rendering, Layouts, Helpers, Callbacks, Translation, Logger
|
4
|
+
class Rails < Base
|
9
5
|
include ActionController::RequestForgeryProtection
|
10
6
|
|
11
|
-
|
12
|
-
require 'cell/rails3_0_strategy'
|
13
|
-
elsif Cells.rails3_1_or_more?
|
14
|
-
require 'cell/rails3_1_strategy'
|
15
|
-
end
|
7
|
+
abstract!
|
16
8
|
|
17
|
-
|
18
|
-
|
19
|
-
options = args.first.is_a?(::Hash) ? args.first : {} # this is copied from #render by intention.
|
20
|
-
|
21
|
-
return controller.render(*args, &block) if options[:state] or options[:view]
|
22
|
-
super
|
23
|
-
end
|
9
|
+
module Metal
|
10
|
+
delegate :session, :params, :request, :config, :env, :url_options, :to => :parent_controller
|
24
11
|
end
|
25
12
|
|
13
|
+
include Metal
|
14
|
+
|
26
15
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
class << self
|
17
|
+
def create_cell(controller, *args)
|
18
|
+
new(controller)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
# Run builder block in controller instance context.
|
23
|
+
def run_builder_block(block, controller, *args)
|
24
|
+
controller.instance_exec(*args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_cell_state(cell, state, *args)
|
28
|
+
args.shift # remove the controller instance.
|
29
|
+
cell.render_state(state, *args)
|
31
30
|
end
|
32
31
|
end
|
33
|
-
|
34
|
-
|
35
|
-
module Metal
|
36
|
-
delegate :session, :params, :request, :config, :env, :url_options, :to => :parent_controller
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
include VersionStrategy
|
41
|
-
include Metal
|
42
|
-
include Rendering
|
43
|
-
include Caching
|
44
32
|
|
45
33
|
attr_reader :parent_controller
|
46
|
-
|
47
|
-
|
48
|
-
|
34
|
+
|
49
35
|
def initialize(parent_controller)
|
50
36
|
super()
|
51
37
|
@parent_controller = parent_controller
|
52
38
|
end
|
53
|
-
|
54
|
-
def self.controller_path
|
55
|
-
@controller_path ||= name.sub(/Cell$/, '').underscore unless anonymous?
|
56
|
-
end
|
57
|
-
|
58
|
-
# Renders the view for the current state and returns the markup.
|
59
|
-
# Don't forget to return the markup itself from the state method.
|
60
|
-
#
|
61
|
-
# === Options
|
62
|
-
# +:view+:: Specifies the name of the view file to render. Defaults to the current state name.
|
63
|
-
# +:layout+:: Renders the state wrapped in the layout. Layouts reside in <tt>app/cells/layouts</tt>.
|
64
|
-
# +:locals+:: Makes the named parameters available as variables in the view.
|
65
|
-
# +:text+:: Just renders plain text.
|
66
|
-
# +:inline+:: Renders an inline template as state view. See ActionView::Base#render for details.
|
67
|
-
# +:file+:: Specifies the name of the file template to render.
|
68
|
-
# +:nothing+:: Doesn't invoke the rendering process.
|
69
|
-
# +:state+:: Instantly invokes another rendering cycle for the passed state and returns. You may pass arbitrary state-args to the called state.
|
70
|
-
# +:format+:: Sets a different template format, e.g. +:json+. Use this option with caution as it currently modifies the global format variable. This might lead to unexpected subsequent render behaviour due to a design flaw in Rails.
|
71
|
-
#
|
72
|
-
# Example:
|
73
|
-
# class MusicianCell < ::Cell::Base
|
74
|
-
# def sing
|
75
|
-
# # ... laalaa
|
76
|
-
# render
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# renders the view <tt>musician/sing.html</tt>.
|
80
|
-
#
|
81
|
-
# def sing
|
82
|
-
# # ... laalaa
|
83
|
-
# render :view => :shout, :layout => 'metal'
|
84
|
-
# end
|
85
|
-
#
|
86
|
-
# renders <tt>musician/shout.html</tt> and wrap it in <tt>app/cells/layouts/metal.html.erb</tt>.
|
87
|
-
#
|
88
|
-
# === #render is explicit!
|
89
|
-
# You can also alter the markup from #render. Just remember to return it.
|
90
|
-
#
|
91
|
-
# def sing
|
92
|
-
# render + render + render
|
93
|
-
# end
|
94
|
-
#
|
95
|
-
# will render three concated views.
|
96
|
-
#
|
97
|
-
# === Partials?
|
98
|
-
#
|
99
|
-
# In Cells we abandoned the term 'partial' in favor of plain 'views' - we don't need to distinguish
|
100
|
-
# between both terms. A cell view is both, a view and a kind of partial as it represents only a fragment
|
101
|
-
# of the page.
|
102
|
-
#
|
103
|
-
# Just use <tt>:view</tt> and enjoy.
|
104
|
-
#
|
105
|
-
# === Using states instead of helpers
|
106
|
-
#
|
107
|
-
# Sometimes it's useful to not only render a view but also invoke the associated state. This is
|
108
|
-
# especially helpful when replacing helpers. Do that with <tt>render :state</tt>.
|
109
|
-
#
|
110
|
-
# def show_cheap_item(item)
|
111
|
-
# render if item.price <= 1
|
112
|
-
# end
|
113
|
-
#
|
114
|
-
# A view could use this state in place of an odd helper.
|
115
|
-
#
|
116
|
-
# - @items.each do |item|
|
117
|
-
# = render({:state => :show_cheap_item}, item)
|
118
|
-
#
|
119
|
-
# This calls the state method which in turn will render its view - if the item isn't too expensive.
|
120
|
-
def render(*args)
|
121
|
-
render_view_for(self.action_name, *args)
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
# Renders the view belonging to the given state. Will raise ActionView::MissingTemplate
|
126
|
-
# if it can't find a view.
|
127
|
-
def render_view_for(state, *args)
|
128
|
-
opts = args.first.is_a?(::Hash) ? args.shift : {}
|
129
|
-
|
130
|
-
return "" if opts[:nothing]
|
131
|
-
|
132
|
-
if opts[:state]
|
133
|
-
opts[:text] = render_state(opts.delete(:state), *args)
|
134
|
-
elsif (opts.keys & [:text, :inline, :file]).blank?
|
135
|
-
process_opts_for(opts, state)
|
136
|
-
end
|
137
|
-
|
138
|
-
render_to_string(opts).html_safe # ActionView::Template::Text doesn't do that for us.
|
139
|
-
end
|
140
39
|
end
|
141
40
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Cell
|
2
|
+
module Rendering
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# Invoke the state method for +state+ which usually renders something nice.
|
6
|
+
def render_state(state, *args)
|
7
|
+
process(state, *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Renders the view for the current state and returns the markup.
|
11
|
+
# Don't forget to return the markup itself from the state method.
|
12
|
+
#
|
13
|
+
# === Options
|
14
|
+
# +:view+:: Specifies the name of the view file to render. Defaults to the current state name.
|
15
|
+
# +:layout+:: Renders the state wrapped in the layout. Layouts reside in <tt>app/cells/layouts</tt>.
|
16
|
+
# +:locals+:: Makes the named parameters available as variables in the view.
|
17
|
+
# +:text+:: Just renders plain text.
|
18
|
+
# +:inline+:: Renders an inline template as state view. See ActionView::Base#render for details.
|
19
|
+
# +:file+:: Specifies the name of the file template to render.
|
20
|
+
# +:nothing+:: Doesn't invoke the rendering process.
|
21
|
+
# +:state+:: Instantly invokes another rendering cycle for the passed state and returns. You may pass arbitrary state-args to the called state.
|
22
|
+
# +:format+:: Sets a different template format, e.g. +:json+. Use this option with caution as it currently modifies the global format variable. This might lead to unexpected subsequent render behaviour due to a design flaw in Rails.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# class MusicianCell < ::Cell::Base
|
26
|
+
# def sing
|
27
|
+
# # ... laalaa
|
28
|
+
# render
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# renders the view <tt>musician/sing.html</tt>.
|
32
|
+
#
|
33
|
+
# def sing
|
34
|
+
# # ... laalaa
|
35
|
+
# render :view => :shout, :layout => 'metal'
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# renders <tt>musician/shout.html</tt> and wrap it in <tt>app/cells/layouts/metal.html.erb</tt>.
|
39
|
+
#
|
40
|
+
# === #render is explicit!
|
41
|
+
# You can also alter the markup from #render. Just remember to return it.
|
42
|
+
#
|
43
|
+
# def sing
|
44
|
+
# render + render + render
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# will render three concated views.
|
48
|
+
#
|
49
|
+
# === Partials?
|
50
|
+
#
|
51
|
+
# In Cells we abandoned the term 'partial' in favor of plain 'views' - we don't need to distinguish
|
52
|
+
# between both terms. A cell view is both, a view and a kind of partial as it represents only a fragment
|
53
|
+
# of the page.
|
54
|
+
#
|
55
|
+
# Just use <tt>:view</tt> and enjoy.
|
56
|
+
#
|
57
|
+
# === Using states instead of helpers
|
58
|
+
#
|
59
|
+
# Sometimes it's useful to not only render a view but also invoke the associated state. This is
|
60
|
+
# especially helpful when replacing helpers. Do that with <tt>render :state</tt>.
|
61
|
+
#
|
62
|
+
# def show_cheap_item(item)
|
63
|
+
# render if item.price <= 1
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# A view could use this state in place of an odd helper.
|
67
|
+
#
|
68
|
+
# - @items.each do |item|
|
69
|
+
# = render({:state => :show_cheap_item}, item)
|
70
|
+
#
|
71
|
+
# This calls the state method which in turn will render its view - if the item isn't too expensive.
|
72
|
+
def render(*args)
|
73
|
+
render_view_for(self.action_name, *args)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
# Renders the view belonging to the given state. Will raise ActionView::MissingTemplate
|
78
|
+
# if it can't find a view.
|
79
|
+
def render_view_for(state, *args)
|
80
|
+
opts = args.first.is_a?(::Hash) ? args.shift : {}
|
81
|
+
|
82
|
+
return "" if opts[:nothing]
|
83
|
+
|
84
|
+
if opts[:state]
|
85
|
+
opts[:text] = render_state(opts.delete(:state), *args)
|
86
|
+
elsif (opts.keys & [:text, :inline, :file]).blank?
|
87
|
+
process_opts_for(opts, state)
|
88
|
+
end
|
89
|
+
|
90
|
+
render_to_string(opts).html_safe # ActionView::Template::Text doesn't do that for us.
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
module ClassMethods
|
95
|
+
# Main entry point for #render_cell.
|
96
|
+
def render_cell_for(name, state, *args)
|
97
|
+
cell = create_cell_for(name, *args)
|
98
|
+
yield cell if block_given?
|
99
|
+
|
100
|
+
render_cell_state(cell, state, *args)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
def render_cell_state(cell, state, *args)
|
105
|
+
cell.render_state(state, *args)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/cell/test_case.rb
CHANGED
@@ -96,7 +96,7 @@ module Cell
|
|
96
96
|
# assert_select html, "h1", "The latest and greatest!"
|
97
97
|
def render_cell(name, state, *args)
|
98
98
|
# DISCUSS: should we allow passing a block here, just as in controllers?
|
99
|
-
@subject_cell = ::Cell::
|
99
|
+
@subject_cell = ::Cell::Rails.create_cell_for(name, @controller, *args)
|
100
100
|
@view_assigns = extract_state_ivars_for(@subject_cell) do
|
101
101
|
@last_invoke = @subject_cell.render_state(state, *args)
|
102
102
|
end
|
@@ -110,7 +110,7 @@ module Cell
|
|
110
110
|
# Example:
|
111
111
|
# assert_equal "Doo Dumm Dumm..." cell(:bassist).play
|
112
112
|
def cell(name, *args, &block)
|
113
|
-
cell = ::Cell::
|
113
|
+
cell = ::Cell::Rails.create_cell_for(name, @controller, *args)
|
114
114
|
cell.instance_eval &block if block_given?
|
115
115
|
ActiveSupport::Deprecation.warn("Passing options to TestCase#cell is deprecated, please use state-args in #render_cell.", caller) if args.present?
|
116
116
|
cell
|
data/lib/cells.rb
CHANGED
@@ -68,7 +68,7 @@ module Cells
|
|
68
68
|
# end
|
69
69
|
#
|
70
70
|
def self.setup
|
71
|
-
yield(Cell::
|
71
|
+
yield(Cell::Rails)
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.rails3_0?
|
@@ -83,7 +83,4 @@ end
|
|
83
83
|
require 'cell/rails'
|
84
84
|
require 'cells/railtie'
|
85
85
|
require 'cells/rails'
|
86
|
-
require 'cells/rails_compat' # fixes a bug in Rails <3.0.4. # TODO: remove me as soon as we support 3.1, only.
|
87
86
|
require 'cell/deprecations'
|
88
|
-
|
89
|
-
Cell::Base = Cell::Rails
|
data/lib/cells/rails.rb
CHANGED
@@ -18,7 +18,7 @@ module Cells
|
|
18
18
|
# cell.markdown! if config.parse_comments?
|
19
19
|
# end
|
20
20
|
def render_cell(name, state, *args, &block)
|
21
|
-
::Cell::
|
21
|
+
::Cell::Rails.render_cell_for(name, state, self, *args, &block)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Expires the cached cell state view, similar to ActionController::expire_fragment.
|
@@ -39,7 +39,7 @@ module Cells
|
|
39
39
|
def expire_cell_state(cell_class, state, args={}, opts=nil)
|
40
40
|
if cell_class.is_a?(Symbol)
|
41
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::
|
42
|
+
cell_class = Cell::Rails.class_from_cell_name(cell_class)
|
43
43
|
end
|
44
44
|
|
45
45
|
key = cell_class.state_cache_key(state, args)
|
@@ -50,7 +50,7 @@ module Cells
|
|
50
50
|
module ActionView
|
51
51
|
# See Cells::Rails::ActionController#render_cell.
|
52
52
|
def render_cell(name, state, *args, &block)
|
53
|
-
::Cell::
|
53
|
+
::Cell::Rails.render_cell_for(name, state, controller, *args, &block)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
data/lib/cells/railtie.rb
CHANGED
data/lib/cells/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
AAAaaargh!
|
data/test/cell_module_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class MusicianCell < Cell::
|
3
|
+
class MusicianCell < Cell::Rails
|
4
4
|
end
|
5
5
|
|
6
6
|
class PianistCell < MusicianCell
|
@@ -9,21 +9,51 @@ end
|
|
9
9
|
class SingerCell < MusicianCell
|
10
10
|
end
|
11
11
|
|
12
|
+
# Used in CellBaseTest.
|
13
|
+
class ShouterCell < Cell::Base
|
14
|
+
def sing
|
15
|
+
render
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
class CellBaseTest < MiniTest::Spec
|
21
|
+
describe "Cell::Base" do
|
22
|
+
it "still have a working #url_for" do
|
23
|
+
cell = Cell::Base.new
|
24
|
+
cell.instance_eval do
|
25
|
+
# You can use #default_url_options.
|
26
|
+
def default_url_options
|
27
|
+
{:host => "cells-project.org"}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
# You could also use a *_url or *_path helper method here.
|
32
|
+
assert_equal "http://cells-project.org/dashboard/show", cell.url_for(:action => :show, :controller => :dashboard)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe ".render_cell_for" do
|
36
|
+
it "invokes controller-less cell" do
|
37
|
+
Cell::Base.view_paths= ["test/app/cells"]
|
38
|
+
assert_equal "AAAaaargh!\n", Cell::Base.render_cell_for(:shouter, :sing)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
12
44
|
|
13
45
|
class CellModuleTest < ActiveSupport::TestCase
|
14
46
|
include Cell::TestCase::TestMethods
|
15
|
-
|
16
|
-
context "Cell::Base" do
|
17
|
-
|
47
|
+
context "Cell::Rails" do
|
18
48
|
# FUNCTIONAL:
|
19
49
|
context "render_cell_for" do
|
20
50
|
should "render the actual cell" do
|
21
|
-
assert_equal "Doo", Cell::
|
51
|
+
assert_equal "Doo", Cell::Rails.render_cell_for(:bassist, :play, @controller)
|
22
52
|
end
|
23
53
|
|
24
54
|
should "accept a block, passing the cell instance" do
|
25
55
|
flag = false
|
26
|
-
html = Cell::
|
56
|
+
html = Cell::Rails.render_cell_for(:bassist, :play, @controller) do |cell|
|
27
57
|
assert_equal BassistCell, cell.class
|
28
58
|
flag = true
|
29
59
|
end
|
@@ -41,7 +71,7 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
41
71
|
end
|
42
72
|
end
|
43
73
|
|
44
|
-
assert_instance_of BassistCell, Cell::
|
74
|
+
assert_instance_of BassistCell, Cell::Rails.create_cell_for("cell_module_test/drummer", :play, @controller)
|
45
75
|
end
|
46
76
|
end
|
47
77
|
|
@@ -67,13 +97,13 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
67
97
|
|
68
98
|
should "execute the block in controller context" do
|
69
99
|
@controller.bassist = true
|
70
|
-
assert_is_a BassistCell, Cell::
|
100
|
+
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
71
101
|
end
|
72
102
|
|
73
103
|
should "limit the builder to the receiving class" do
|
74
|
-
assert_is_a PianistCell, Cell::
|
104
|
+
assert_is_a PianistCell, Cell::Rails.create_cell_for(:pianist, @controller) # don't inherit anything.
|
75
105
|
@controller.bassist = true
|
76
|
-
assert_is_a BassistCell, Cell::
|
106
|
+
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
77
107
|
end
|
78
108
|
|
79
109
|
should "chain build blocks and execute them by ORing them in the same order" do
|
@@ -85,13 +115,13 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
85
115
|
UnknownCell # should never be executed.
|
86
116
|
end
|
87
117
|
|
88
|
-
assert_is_a PianistCell, Cell::
|
118
|
+
assert_is_a PianistCell, Cell::Rails.create_cell_for(:musician, @controller) # bassist is false.
|
89
119
|
@controller.bassist = true
|
90
|
-
assert_is_a BassistCell, Cell::
|
120
|
+
assert_is_a BassistCell, Cell::Rails.create_cell_for(:musician, @controller)
|
91
121
|
end
|
92
122
|
|
93
123
|
should "use the original cell if no builder matches" do
|
94
|
-
assert_is_a MusicianCell, Cell::
|
124
|
+
assert_is_a MusicianCell, Cell::Rails.create_cell_for(:musician, @controller) # bassist is false.
|
95
125
|
end
|
96
126
|
|
97
127
|
should "stop at the first builder returning a valid cell" do
|
@@ -102,12 +132,12 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
102
132
|
BassistCell.build do |opts|
|
103
133
|
SingerCell if opts[:sing_the_song]
|
104
134
|
end
|
105
|
-
assert_kind_of BassistCell, Cell::
|
106
|
-
assert_kind_of SingerCell, Cell::
|
135
|
+
assert_kind_of BassistCell, Cell::Rails.create_cell_for(:bassist, @controller, {})
|
136
|
+
assert_kind_of SingerCell, Cell::Rails.create_cell_for(:bassist, @controller, {:sing_the_song => true})
|
107
137
|
end
|
108
138
|
|
109
139
|
should "create the original target class if no block matches" do
|
110
|
-
assert_kind_of PianistCell, Cell::
|
140
|
+
assert_kind_of PianistCell, Cell::Rails.create_cell_for(:pianist, @controller)
|
111
141
|
end
|
112
142
|
|
113
143
|
should "builders should return an empty array per default" do
|
@@ -116,7 +146,7 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
116
146
|
end
|
117
147
|
|
118
148
|
should "provide class_from_cell_name" do
|
119
|
-
assert_equal BassistCell, ::Cell::
|
149
|
+
assert_equal BassistCell, ::Cell::Rails.class_from_cell_name('bassist')
|
120
150
|
end
|
121
151
|
|
122
152
|
if Cells.rails3_0?
|
@@ -129,7 +159,7 @@ class CellModuleTest < ActiveSupport::TestCase
|
|
129
159
|
end
|
130
160
|
|
131
161
|
should "provide cell_name for modules, too" do
|
132
|
-
class SingerCell < Cell::
|
162
|
+
class SingerCell < Cell::Rails
|
133
163
|
end
|
134
164
|
|
135
165
|
assert_equal "cell_module_test/singer", CellModuleTest::SingerCell.cell_name
|
data/test/cells_module_test.rb
CHANGED
@@ -4,11 +4,11 @@ class CellsModuleTest < ActiveSupport::TestCase
|
|
4
4
|
context "Cells" do
|
5
5
|
context "view_paths" do
|
6
6
|
setup do
|
7
|
-
@old_view_paths = Cell::
|
7
|
+
@old_view_paths = Cell::Rails.view_paths.clone
|
8
8
|
end
|
9
9
|
|
10
10
|
teardown do
|
11
|
-
Cell::
|
11
|
+
Cell::Rails.view_paths = @old_view_paths
|
12
12
|
end
|
13
13
|
|
14
14
|
should "provide .setup" do
|
@@ -16,7 +16,7 @@ class CellsModuleTest < ActiveSupport::TestCase
|
|
16
16
|
c.append_view_path "/road/to/nowhere"
|
17
17
|
end
|
18
18
|
|
19
|
-
assert_equal "/road/to/nowhere", Cell::
|
19
|
+
assert_equal "/road/to/nowhere", Cell::Rails.view_paths.last.to_s
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
data/test/deprecations_test.rb
CHANGED
@@ -37,7 +37,7 @@ class DeprecationsTest < ActiveSupport::TestCase
|
|
37
37
|
render :text => options[:note]
|
38
38
|
end
|
39
39
|
end
|
40
|
-
assert_equal "C-minor", Cell::
|
40
|
+
assert_equal "C-minor", Cell::Rails.render_cell_for(:songwriter, :listen, @controller, :note => "C-minor")
|
41
41
|
end
|
42
42
|
|
43
43
|
should "pass options as state-args and still set #options otherwise" do
|
@@ -46,7 +46,7 @@ class DeprecationsTest < ActiveSupport::TestCase
|
|
46
46
|
render :text => args[:note] + options[:note].to_s
|
47
47
|
end
|
48
48
|
end
|
49
|
-
assert_equal "C-minorC-minor", Cell::
|
49
|
+
assert_equal "C-minorC-minor", Cell::Rails.render_cell_for(:songwriter, :listen, @controller, :note => "C-minor")
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
data/test/helper_test.rb
CHANGED
data/test/rails/caching_test.rb
CHANGED
@@ -109,11 +109,11 @@ class CachingUnitTest < ActiveSupport::TestCase
|
|
109
109
|
|
110
110
|
should "accept cache options" do
|
111
111
|
key = @class.state_cache_key(:tock, :volume => 9)
|
112
|
-
assert Cell::
|
112
|
+
assert Cell::Rails.cache_store.write(key, 'ONE!')
|
113
113
|
|
114
114
|
MusicianController.new.expire_cell_state(DirectorCell, :tock, :volume => 9)
|
115
115
|
assert_equal "1", @class.cache_store.read(@key)
|
116
|
-
assert_not ::Cell::
|
116
|
+
assert_not ::Cell::Rails.cache_store.read(key)
|
117
117
|
end
|
118
118
|
|
119
119
|
should "raise a deprecation notice when passing in a :symbol" do
|
data/test/rails/cells_test.rb
CHANGED
@@ -48,13 +48,13 @@ class RailsCellsTest < ActiveSupport::TestCase
|
|
48
48
|
|
49
49
|
context "A rails cell" do
|
50
50
|
should "respond to DEFAULT_VIEW_PATHS" do
|
51
|
-
assert_equal ["app/cells"], Cell::
|
51
|
+
assert_equal ["app/cells"], Cell::Rails::DEFAULT_VIEW_PATHS
|
52
52
|
end
|
53
53
|
|
54
54
|
should "respond to .setup_view_paths!" do
|
55
|
-
swap( Cell::
|
56
|
-
Cell::
|
57
|
-
assert_equal ActionView::PathSet.new(Cell::Rails::DEFAULT_VIEW_PATHS), Cell::
|
55
|
+
swap( Cell::Rails, :view_paths => []) do
|
56
|
+
Cell::Rails.setup_view_paths!
|
57
|
+
assert_equal ActionView::PathSet.new(Cell::Rails::DEFAULT_VIEW_PATHS), Cell::Rails.view_paths
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -63,8 +63,8 @@ class RailsCellsTest < ActiveSupport::TestCase
|
|
63
63
|
end
|
64
64
|
|
65
65
|
should "respond to view_paths=" do
|
66
|
-
swap( Cell::
|
67
|
-
assert_kind_of ActionView::PathSet, Cell::
|
66
|
+
swap( Cell::Rails, :view_paths => ['you', 'are', 'here']) do
|
67
|
+
assert_kind_of ActionView::PathSet, Cell::Rails.view_paths, "must not wipe out the PathSet"
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
data/test/test_case_test.rb
CHANGED
@@ -12,8 +12,14 @@ class TestCaseTest < Cell::TestCase
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
context "#render_cell" do
|
16
|
+
should "invokes the state" do
|
17
|
+
assert_equal "Doo", render_cell(:bassist, :play)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "accept state args" do
|
21
|
+
assert_equal "*shouts* Listen!\n", render_cell(:bassist, :shout, :words => "Listen!")
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
should "respond to #assert_selector with 3 args" do
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 3
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 3.
|
7
|
+
- 8
|
8
|
+
- 0
|
9
|
+
version: 3.8.0
|
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-12-
|
17
|
+
date: 2011-12-21 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -110,6 +110,19 @@ dependencies:
|
|
110
110
|
version: "0"
|
111
111
|
type: :development
|
112
112
|
version_requirements: *id007
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: minitest
|
115
|
+
prerelease: false
|
116
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
124
|
+
type: :development
|
125
|
+
version_requirements: *id008
|
113
126
|
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.
|
114
127
|
email:
|
115
128
|
- apotonick@gmail.com
|
@@ -130,16 +143,17 @@ files:
|
|
130
143
|
- cells.gemspec
|
131
144
|
- lib/cell.rb
|
132
145
|
- lib/cell/base.rb
|
146
|
+
- lib/cell/builder.rb
|
133
147
|
- lib/cell/caching.rb
|
134
148
|
- lib/cell/deprecations.rb
|
135
149
|
- lib/cell/rails.rb
|
136
150
|
- lib/cell/rails3_0_strategy.rb
|
137
151
|
- lib/cell/rails3_1_strategy.rb
|
152
|
+
- lib/cell/rendering.rb
|
138
153
|
- lib/cell/test_case.rb
|
139
154
|
- lib/cells.rb
|
140
155
|
- lib/cells/cells.rake
|
141
156
|
- lib/cells/rails.rb
|
142
|
-
- lib/cells/rails_compat.rb
|
143
157
|
- lib/cells/railtie.rb
|
144
158
|
- lib/cells/version.rb
|
145
159
|
- lib/generators/USAGE
|
@@ -182,6 +196,7 @@ files:
|
|
182
196
|
- test/app/cells/layouts/metal.html.erb
|
183
197
|
- test/app/cells/producer/capture.html.erb
|
184
198
|
- test/app/cells/producer/content_for.html.erb
|
199
|
+
- test/app/cells/shouter/sing.html.erb
|
185
200
|
- test/app/cells/trumpeter/promote.html.erb
|
186
201
|
- test/app/cells/trumpeter_cell.rb
|
187
202
|
- test/cell_generator_test.rb
|
data/lib/cells/rails_compat.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# TODO: remove me when Cells supports 3.1, only.
|
2
|
-
if Rails::VERSION::MINOR == 0 and Rails::VERSION::TINY <= 3
|
3
|
-
module AbstractController
|
4
|
-
module Callbacks
|
5
|
-
def process_action(method_name, *args) # Fixed in 3.0.4.
|
6
|
-
run_callbacks(:process_action, method_name) do
|
7
|
-
super
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|