cells 4.0.0.beta6 → 4.0.0.rc1
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 +4 -4
- data/CHANGES.md +4 -0
- data/README.md +316 -371
- data/cells.gemspec +1 -3
- data/lib/cell/caching.rb +1 -0
- data/lib/cell/rails.rb +7 -0
- data/lib/cell/railtie.rb +2 -5
- data/lib/cell/version.rb +1 -1
- data/lib/cell/view_model.rb +24 -30
- data/test/builder_test.rb +10 -7
- data/test/caching_test.rb +47 -40
- data/test/rails4.2/app/cells/song_cell.rb +7 -0
- data/test/rails4.2/app/controllers/songs_controller.rb +8 -0
- data/test/rails4.2/test/integration/formtastic_test.rb +1 -0
- data/test/rails4.2/test/integration/simple_form_test.rb +1 -0
- data/test/rails4.2/test/integration/url_helper_test.rb +16 -5
- data/test/templates_test.rb +1 -1
- data/test/test_helper.rb +2 -0
- data/test/twin_test.rb +20 -20
- metadata +4 -18
data/cells.gemspec
CHANGED
@@ -21,12 +21,10 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.add_dependency "uber", "~> 0.0.9"
|
23
23
|
spec.add_dependency 'tilt', '>= 1.4', '< 3'
|
24
|
-
spec.add_dependency 'disposable', '~> 0.0.8'
|
25
|
-
|
26
24
|
|
27
25
|
spec.add_development_dependency "rake"
|
28
26
|
spec.add_development_dependency "minitest-reporters"
|
29
27
|
spec.add_development_dependency "capybara"
|
30
28
|
|
31
|
-
spec.add_development_dependency "cells-erb", ">= 0.0.
|
29
|
+
spec.add_development_dependency "cells-erb", ">= 0.0.4"
|
32
30
|
end
|
data/lib/cell/caching.rb
CHANGED
data/lib/cell/rails.rb
CHANGED
@@ -34,6 +34,13 @@ module Cell
|
|
34
34
|
module ViewModel
|
35
35
|
extend ActiveSupport::Concern
|
36
36
|
|
37
|
+
# DISCUSS: who actually uses forgery protection with cells? it is not working since 4, anyway?
|
38
|
+
# include ActionController::RequestForgeryProtection
|
39
|
+
included do
|
40
|
+
extend Uber::Delegates
|
41
|
+
delegates :parent_controller, :session, :params, :request, :config, :env, :url_options
|
42
|
+
end
|
43
|
+
|
37
44
|
def call(*)
|
38
45
|
super.html_safe
|
39
46
|
end
|
data/lib/cell/railtie.rb
CHANGED
@@ -11,10 +11,6 @@ module Cell
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
# initializer 'cells.template_engine' do |app|
|
15
|
-
# ViewModel.template_engine = app.config.app_generators.rails.fetch(:template_engine, 'erb').to_s
|
16
|
-
# end
|
17
|
-
|
18
14
|
# ruthlessly stolen from the zurb-foundation gem.
|
19
15
|
initializer 'cells.update_asset_paths' do |app|
|
20
16
|
Array(app.config.cells.with_assets).each do |cell_class|
|
@@ -38,7 +34,7 @@ module Cell
|
|
38
34
|
end
|
39
35
|
|
40
36
|
initializer "cells.include_default_helpers" do
|
41
|
-
#include
|
37
|
+
# include asset helpers (image_path, font_path, ect)
|
42
38
|
ViewModel.class_eval do
|
43
39
|
include ActionView::Helpers::UrlHelper
|
44
40
|
include ::Cell::RailsExtensions::HelpersAreShit
|
@@ -58,6 +54,7 @@ module Cell
|
|
58
54
|
ViewModel.send(:include, Cell::Haml) if Cell.const_defined?(:Haml)
|
59
55
|
ViewModel.send(:include, Cell::Slim) if Cell.const_defined?(:Slim)
|
60
56
|
end
|
57
|
+
# ViewModel.template_engine = app.config.app_generators.rails.fetch(:template_engine, 'erb').to_s
|
61
58
|
|
62
59
|
initializer('cells.development') do |app|
|
63
60
|
if Rails.env == "development"
|
data/lib/cell/version.rb
CHANGED
data/lib/cell/view_model.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
# no helper_method calls
|
2
|
-
# no instance variables
|
3
|
-
# no locals
|
4
|
-
# options are automatically made instance methods via constructor.
|
5
|
-
# call "helpers" in class
|
6
|
-
|
7
1
|
# TODO: warn when using ::property but not passing in model in constructor.
|
8
2
|
module Cell
|
9
3
|
class ViewModel
|
@@ -36,29 +30,21 @@ module Cell
|
|
36
30
|
@controller_path ||= util.underscore(name.sub(/Cell$/, ''))
|
37
31
|
end
|
38
32
|
|
39
|
-
# FIXME: this is all rails-only.
|
40
|
-
# DISCUSS: who actually uses forgery protection with cells? it is not working since 4, anyway?
|
41
|
-
# include ActionController::RequestForgeryProtection
|
42
|
-
delegates :parent_controller, :session, :params, :request, :config, :env, :url_options
|
43
|
-
|
44
33
|
attr_reader :model
|
45
34
|
|
46
35
|
|
47
36
|
module Helpers
|
37
|
+
# Constantizes name, call builders and returns instance.
|
38
|
+
def cell(name, *args, &block) # classic Rails fuzzy API.
|
39
|
+
class_from_cell_name(name).(*args, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
48
43
|
# Renders collection of cells.
|
49
|
-
def
|
44
|
+
def render_collection(array, options) # private.
|
50
45
|
method = options.delete(:method) || :show
|
51
46
|
join = options.delete(:collection_join)
|
52
|
-
array.collect { |model|
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns cell instance.
|
56
|
-
def cell(name, model=nil, options={}, &block) # classic Rails fuzzy API.
|
57
|
-
if model.is_a?(Hash) and array = model.delete(:collection)
|
58
|
-
return _collection(name, array, model.merge(options))
|
59
|
-
end
|
60
|
-
|
61
|
-
cell_for(name, model, options, &block)
|
47
|
+
array.collect { |model| build(*[model, options]).call(method) }.join(join).html_safe
|
62
48
|
end
|
63
49
|
end
|
64
50
|
extend Helpers
|
@@ -71,18 +57,25 @@ module Cell
|
|
71
57
|
|
72
58
|
include Helpers
|
73
59
|
|
74
|
-
#
|
60
|
+
# Public entry point. Use this to instantiate cells with builders.
|
61
|
+
#
|
62
|
+
# SongCell.(@song)
|
63
|
+
# SongCell.(collection: Song.all)
|
64
|
+
def call(model=nil, options={}, &block)
|
65
|
+
if model.is_a?(Hash) and array = model.delete(:collection)
|
66
|
+
return render_collection(array, model.merge(options))
|
67
|
+
end
|
75
68
|
|
76
|
-
|
77
|
-
class_from_cell_name(name).build_cell(*args)
|
69
|
+
build(model, options)
|
78
70
|
end
|
79
71
|
|
80
|
-
def
|
81
|
-
|
72
|
+
def build(*args) # semi-public.
|
73
|
+
class_builder.call(*args).new(*args) # Uber::Builder::class_builder.
|
82
74
|
end
|
83
75
|
|
84
|
-
|
85
|
-
|
76
|
+
private
|
77
|
+
def class_from_cell_name(name)
|
78
|
+
"#{name}_cell".classify.constantize
|
86
79
|
end
|
87
80
|
end
|
88
81
|
|
@@ -185,10 +178,11 @@ module Cell
|
|
185
178
|
module TemplateFor
|
186
179
|
def find_template(options)
|
187
180
|
template_options = template_options_for(options) # imported by Erb, Haml, etc.
|
181
|
+
# required options: :template_class, :suffix. everything else is passed to the template implementation.
|
188
182
|
|
189
183
|
view = options[:view]
|
190
184
|
prefixes = options[:prefixes]
|
191
|
-
suffix = template_options
|
185
|
+
suffix = template_options.delete(:suffix)
|
192
186
|
view = "#{view}.#{suffix}"
|
193
187
|
|
194
188
|
template_for(prefixes, view, template_options) or raise TemplateMissingError.new(prefixes, view)
|
data/test/builder_test.rb
CHANGED
@@ -34,25 +34,28 @@ class BuilderTest < MiniTest::Spec
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# the original class is used when no builder matches.
|
37
|
-
it {
|
37
|
+
it { SongCell.(Song.new("Nation States"), {}).must_be_instance_of SongCell }
|
38
38
|
|
39
39
|
it do
|
40
|
-
cell =
|
41
|
-
cell.must_be_instance_of
|
40
|
+
cell = SongCell.(Hit.new("New York"), {})
|
41
|
+
cell.must_be_instance_of HitCell
|
42
42
|
cell.options.must_equal({})
|
43
43
|
end
|
44
44
|
|
45
45
|
it do
|
46
|
-
cell =
|
47
|
-
cell.must_be_instance_of
|
46
|
+
cell = SongCell.(Song.new("San Francisco"), evergreen: true)
|
47
|
+
cell.must_be_instance_of EvergreenCell
|
48
48
|
cell.options.must_equal({:evergreen=>true})
|
49
49
|
end
|
50
50
|
|
51
|
+
# without arguments.
|
52
|
+
it { SongCell.(Hit.new("Frenzy")).must_be_instance_of HitCell }
|
53
|
+
|
51
54
|
# with collection.
|
52
|
-
it {
|
55
|
+
it { SongCell.(collection: [Song.new("Nation States"), Hit.new("New York")]).must_equal "* Nation States* **New York**" }
|
53
56
|
|
54
57
|
# with Concept
|
55
58
|
class Track < Cell::Concept
|
56
59
|
end
|
57
|
-
it {
|
60
|
+
it { Track.().must_be_instance_of Track }
|
58
61
|
end
|
data/test/caching_test.rb
CHANGED
@@ -140,91 +140,98 @@ class CachingTest < MiniTest::Spec
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# let (:cell) { DirectorCell.new(nil) }
|
143
|
-
def
|
143
|
+
def director_cell(*args)
|
144
144
|
DirectorCell.new(*args)
|
145
145
|
end
|
146
146
|
|
147
147
|
# no caching when turned off.
|
148
148
|
it do
|
149
|
-
|
149
|
+
director_cell.class.cache :show
|
150
150
|
ActionController::Base.perform_caching = false
|
151
151
|
|
152
|
-
|
153
|
-
|
152
|
+
director_cell(1).call.must_equal "1"
|
153
|
+
director_cell(2).call.must_equal "2"
|
154
154
|
end
|
155
155
|
|
156
156
|
# cache forever when no options.
|
157
157
|
it do
|
158
|
-
|
159
|
-
|
160
|
-
|
158
|
+
director_cell.class.cache :show
|
159
|
+
director_cell(1).call.must_equal "1"
|
160
|
+
director_cell(2).call.must_equal "1"
|
161
|
+
end
|
162
|
+
|
163
|
+
# caches with string state name.
|
164
|
+
it do
|
165
|
+
director_cell.class.cache :show
|
166
|
+
director_cell(1).("show").must_equal "1"
|
167
|
+
director_cell(2).("show").must_equal "1"
|
161
168
|
end
|
162
169
|
|
163
170
|
|
164
171
|
# no caching when state not configured.
|
165
172
|
it do
|
166
|
-
|
173
|
+
director_cell.class.class_eval do
|
167
174
|
def dictate
|
168
175
|
@counter
|
169
176
|
end
|
170
177
|
end
|
171
178
|
|
172
|
-
|
173
|
-
|
179
|
+
director_cell(1).call(:dictate).must_equal "1"
|
180
|
+
director_cell(2).call(:dictate).must_equal "2"
|
174
181
|
end
|
175
182
|
|
176
183
|
# compute key with cell properties from #initialize.
|
177
184
|
it do
|
178
|
-
|
185
|
+
director_cell.class.cache :show do
|
179
186
|
@counter < 3 ? {:count => "<"} : {:count => ">"}
|
180
187
|
end
|
181
188
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
189
|
+
director_cell(1).call.must_equal "1"
|
190
|
+
director_cell(2).call.must_equal "1"
|
191
|
+
director_cell(3).call.must_equal "3"
|
192
|
+
director_cell(4).call.must_equal "3"
|
186
193
|
end
|
187
194
|
|
188
195
|
# compute key with instance method
|
189
196
|
it do
|
190
|
-
|
191
|
-
|
197
|
+
director_cell.class.cache :show, :version
|
198
|
+
director_cell.class.class_eval do
|
192
199
|
def version
|
193
200
|
@counter < 3 ? {:count => "<"} : {:count => ">"}
|
194
201
|
end
|
195
202
|
end
|
196
203
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
204
|
+
director_cell(1).call.must_equal "1"
|
205
|
+
director_cell(2).call.must_equal "1"
|
206
|
+
director_cell(3).call.must_equal "3"
|
207
|
+
director_cell(4).call.must_equal "3"
|
201
208
|
end
|
202
209
|
|
203
210
|
# allow returning strings for key
|
204
211
|
it do
|
205
|
-
|
212
|
+
director_cell.class.cache :show do
|
206
213
|
@counter < 3 ? "<" : ">"
|
207
214
|
end
|
208
215
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
216
|
+
director_cell(1).call.must_equal "1"
|
217
|
+
director_cell(2).call.must_equal "1"
|
218
|
+
director_cell(3).call.must_equal "3"
|
219
|
+
director_cell(4).call.must_equal "3"
|
213
220
|
end
|
214
221
|
|
215
222
|
# allows conditional ifs.
|
216
223
|
it do
|
217
|
-
|
224
|
+
director_cell.class.cache :show, if: lambda { @counter < 3 }
|
218
225
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
226
|
+
director_cell(1).call.must_equal "1"
|
227
|
+
director_cell(2).call.must_equal "1"
|
228
|
+
director_cell(3).call.must_equal "3"
|
229
|
+
director_cell(4).call.must_equal "4"
|
223
230
|
end
|
224
231
|
|
225
232
|
# allows conditional ifs with instance method.
|
226
233
|
it do
|
227
|
-
|
234
|
+
director_cell.class.class_eval do
|
228
235
|
cache :show, if: :smaller?
|
229
236
|
|
230
237
|
def smaller?
|
@@ -232,22 +239,22 @@ class CachingTest < MiniTest::Spec
|
|
232
239
|
end
|
233
240
|
end
|
234
241
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
242
|
+
director_cell(1).call.must_equal "1"
|
243
|
+
director_cell(2).call.must_equal "1"
|
244
|
+
director_cell(3).call.must_equal "3"
|
245
|
+
director_cell(4).call.must_equal "4"
|
239
246
|
end
|
240
247
|
|
241
248
|
|
242
249
|
unless ::ActionPack::VERSION::MAJOR == 3 and ::ActionPack::VERSION::MINOR >= 2 # bug in 3.2.
|
243
250
|
describe "utf-8" do
|
244
251
|
before do
|
245
|
-
@key =
|
252
|
+
@key = director_cell.class.state_cache_key(:utf8)
|
246
253
|
end
|
247
254
|
|
248
255
|
it "has the correct encoding when reading from cache" do
|
249
|
-
assert_equal "UTF-8",
|
250
|
-
assert_equal "UTF-8",
|
256
|
+
assert_equal "UTF-8", director_cell.call(:utf8).encoding.to_s
|
257
|
+
assert_equal "UTF-8", director_cell.cache_store.read(@key).encoding.to_s
|
251
258
|
end
|
252
259
|
end
|
253
260
|
end
|
@@ -264,7 +271,7 @@ class CachingTest < MiniTest::Spec
|
|
264
271
|
end
|
265
272
|
|
266
273
|
it do
|
267
|
-
cellule = self.
|
274
|
+
cellule = self.director_cell
|
268
275
|
|
269
276
|
cellule.instance_eval do
|
270
277
|
def cache_store;
|
@@ -2,4 +2,11 @@ class SongCell < Cell::ViewModel
|
|
2
2
|
def show
|
3
3
|
"happy"
|
4
4
|
end
|
5
|
+
|
6
|
+
# include ActionView::Helpers::AssetUrlHelper
|
7
|
+
# include Sprockets::Rails::Helper
|
8
|
+
|
9
|
+
# self.assets_prefix = Rails.application.config.assets.prefix
|
10
|
+
# self.assets_environment = Rails.application.assets
|
11
|
+
# self.digest_assets = Rails.application.config.assets[:digest]
|
5
12
|
end
|
@@ -2,6 +2,7 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
class FormForTestTest < MiniTest::Spec
|
4
4
|
include Cell::Testing
|
5
|
+
controller SongsController # provides #url_options.
|
5
6
|
|
6
7
|
it do
|
7
8
|
cell("formtastic").().gsub(/\s\s/, "").must_equal %{<form novalidate=\"novalidate\" class=\"formtastic song\" id=\"edit_song_1\" action=\"/songs/1\" accept-charset=\"UTF-8\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input type=\"hidden\" name=\"_method\" value=\"patch\" /> First <li class=\"string input required stringish\" id=\"song_id_input\"><label for=\"song_id\" class=\"label\">Id<abbr title=\"required\">*</abbr></label><input id=\"song_id\" type=\"text\" value=\"1\" name=\"song[id]\" /></li><li class=\"string input required stringish\" id=\"song_artist_id_input\"><label for=\"song_artist_id\" class=\"label\">Id<abbr title=\"required\">*</abbr></label><input id=\"song_artist_id\" type=\"text\" name=\"song[artist][id]\" /></li><fieldset class=\"actions\"><ol> <input type=\"submit\" name=\"commit\" value=\"Go!\" as=\"button\" class=\"btn btn-primary\" />
|
@@ -2,6 +2,7 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
class SimpleFormTest < MiniTest::Spec
|
4
4
|
include Cell::Testing
|
5
|
+
controller SongsController # provides #url_options.
|
5
6
|
|
6
7
|
it do
|
7
8
|
cell("simple_form").().gsub(/\s\s/, "").must_equal %{<form class=\"simple_form edit_song\" id=\"edit_song_1\" action=\"/songs/1\" accept-charset=\"UTF-8\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input type=\"hidden\" name=\"_method\" value=\"patch\" /> First <div class=\"input string required song_id\"><label class=\"string required\" for=\"song_id\"><abbr title=\"required\">*</abbr> Id</label><input class=\"string required\" required=\"required\" aria-required=\"true\" type=\"text\" value=\"1\" name=\"song[id]\" id=\"song_id\" /></div><div class=\"input string required song_artist_id\"><label class=\"string required\" for=\"song_artist_id\"><abbr title=\"required\">*</abbr> Id</label><input class=\"string required\" required=\"required\" aria-required=\"true\" type=\"text\" name=\"song[artist][id]\" id=\"song_artist_id\" /></div>
|
@@ -11,15 +11,26 @@ class UrlHelperTest < MiniTest::Spec
|
|
11
11
|
def show
|
12
12
|
url_for(model)
|
13
13
|
end
|
14
|
-
|
15
|
-
def default_url_options
|
16
|
-
{host: "rails.sucks"}
|
17
|
-
end
|
18
14
|
end
|
19
15
|
|
20
16
|
let (:song_cell) { Cell.new(Song.new, controller: controller) }
|
21
17
|
|
22
18
|
# path helpers work in cell instance.
|
23
19
|
it { song_cell.songs_path.must_equal "/songs" }
|
24
|
-
it { song_cell.().must_equal "http://
|
20
|
+
it { song_cell.().must_equal "http://test.host/songs/1" }
|
25
21
|
end
|
22
|
+
|
23
|
+
|
24
|
+
class UrlTest < ActionDispatch::IntegrationTest
|
25
|
+
include ::Capybara::DSL
|
26
|
+
|
27
|
+
it do
|
28
|
+
visit "/songs/new" # cell.url_for(Song.new)
|
29
|
+
page.text.must_equal "http://www.example.com/songs/1"
|
30
|
+
end
|
31
|
+
|
32
|
+
# it do
|
33
|
+
# visit "/songs/1/edit"
|
34
|
+
# page.text.must_equal "http://www.example.com/songs/1"
|
35
|
+
# end
|
36
|
+
end
|