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.
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.2"
29
+ spec.add_development_dependency "cells-erb", ">= 0.0.4"
32
30
  end
data/lib/cell/caching.rb CHANGED
@@ -43,6 +43,7 @@ module Cell
43
43
 
44
44
 
45
45
  def render_state(state, *args)
46
+ state = state.to_sym
46
47
  return super(state, *args) unless cache?(state, *args)
47
48
 
48
49
  key = self.class.state_cache_key(state, self.class.version_procs[state].evaluate(self, *args))
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 assert helpers (image_path, font_path, ect)
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
@@ -1,3 +1,3 @@
1
1
  module Cell
2
- VERSION = "4.0.0.beta6"
2
+ VERSION = "4.0.0.rc1"
3
3
  end
@@ -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 _collection(name, array, options) # private.
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| cell_for(name, *[model, options]).call(method) }.join(join).html_safe
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
- # DISCUSS: introduce ::for which takes constant? rename ::build_cell to ::build?
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
- def cell_for(name, *args)
77
- class_from_cell_name(name).build_cell(*args)
69
+ build(model, options)
78
70
  end
79
71
 
80
- def class_from_cell_name(name)
81
- "#{name}_cell".classify.constantize
72
+ def build(*args) # semi-public.
73
+ class_builder.call(*args).new(*args) # Uber::Builder::class_builder.
82
74
  end
83
75
 
84
- def build_cell(*args)
85
- class_builder.call(*args).new(*args) # Uber::Builder::class_builder.
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[:suffix]
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 { Cell::ViewModel.cell("builder_test/song", Song.new("Nation States"), {}).must_be_instance_of BuilderTest::SongCell }
37
+ it { SongCell.(Song.new("Nation States"), {}).must_be_instance_of SongCell }
38
38
 
39
39
  it do
40
- cell = Cell::ViewModel.cell("builder_test/song", Hit.new("New York"), {})
41
- cell.must_be_instance_of BuilderTest::HitCell
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 = Cell::ViewModel.cell("builder_test/song", Song.new("San Francisco"), evergreen: true)
47
- cell.must_be_instance_of BuilderTest::EvergreenCell
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 { Cell::ViewModel.cell("builder_test/song", collection: [Song.new("Nation States"), Hit.new("New York")]).must_equal "* Nation States* **New York**" }
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 { Cell::Concept.cell("builder_test/track").must_be_instance_of Track }
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 cellule(*args)
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
- cellule.class.cache :show
149
+ director_cell.class.cache :show
150
150
  ActionController::Base.perform_caching = false
151
151
 
152
- cellule(1).call.must_equal "1"
153
- cellule(2).call.must_equal "2"
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
- cellule.class.cache :show
159
- cellule(1).call.must_equal "1"
160
- cellule(2).call.must_equal "1"
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
- cellule.class.class_eval do
173
+ director_cell.class.class_eval do
167
174
  def dictate
168
175
  @counter
169
176
  end
170
177
  end
171
178
 
172
- cellule(1).call(:dictate).must_equal "1"
173
- cellule(2).call(:dictate).must_equal "2"
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
- cellule.class.cache :show do
185
+ director_cell.class.cache :show do
179
186
  @counter < 3 ? {:count => "<"} : {:count => ">"}
180
187
  end
181
188
 
182
- cellule(1).call.must_equal "1"
183
- cellule(2).call.must_equal "1"
184
- cellule(3).call.must_equal "3"
185
- cellule(4).call.must_equal "3"
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
- cellule.class.cache :show, :version
191
- cellule.class.class_eval do
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
- cellule(1).call.must_equal "1"
198
- cellule(2).call.must_equal "1"
199
- cellule(3).call.must_equal "3"
200
- cellule(4).call.must_equal "3"
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
- cellule.class.cache :show do
212
+ director_cell.class.cache :show do
206
213
  @counter < 3 ? "<" : ">"
207
214
  end
208
215
 
209
- cellule(1).call.must_equal "1"
210
- cellule(2).call.must_equal "1"
211
- cellule(3).call.must_equal "3"
212
- cellule(4).call.must_equal "3"
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
- cellule.class.cache :show, if: lambda { @counter < 3 }
224
+ director_cell.class.cache :show, if: lambda { @counter < 3 }
218
225
 
219
- cellule(1).call.must_equal "1"
220
- cellule(2).call.must_equal "1"
221
- cellule(3).call.must_equal "3"
222
- cellule(4).call.must_equal "4"
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
- cellule.class.class_eval do
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
- cellule(1).call.must_equal "1"
236
- cellule(2).call.must_equal "1"
237
- cellule(3).call.must_equal "3"
238
- cellule(4).call.must_equal "4"
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 = cellule.class.state_cache_key(:utf8)
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", cellule.call(:utf8).encoding.to_s
250
- assert_equal "UTF-8", cellule.cache_store.read(@key).encoding.to_s
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.cellule
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
@@ -6,4 +6,12 @@ class SongsController < ApplicationController
6
6
  def index
7
7
  render text: cell(:song).()
8
8
  end
9
+
10
+ def new
11
+ render text: cell(:song).url_for(Song.new)
12
+ end
13
+
14
+ def edit
15
+ render text: cell(:song).video_path(1)
16
+ end
9
17
  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=\"&#x2713;\" /><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=\"&#x2713;\" /><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://rails.sucks/songs/1" }
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