volt 0.9.5.pre4 → 0.9.5.pre5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +13 -5
- data/app/volt/assets/css/{notices.css.scss → notices.scss} +0 -0
- data/app/volt/models/active_volt_instance.rb +1 -1
- data/app/volt/tasks/live_query/live_query.rb +11 -3
- data/app/volt/tasks/store_tasks.rb +14 -17
- data/lib/volt/cli.rb +22 -0
- data/lib/volt/cli/asset_compile.rb +63 -63
- data/lib/volt/cli/base_index_renderer.rb +26 -0
- data/lib/volt/cli/generate.rb +1 -1
- data/lib/volt/config.rb +1 -0
- data/lib/volt/controllers/model_controller.rb +37 -1
- data/lib/volt/extra_core/array.rb +22 -0
- data/lib/volt/models/array_model.rb +7 -1
- data/lib/volt/models/errors.rb +1 -1
- data/lib/volt/models/field_helpers.rb +36 -21
- data/lib/volt/models/model.rb +16 -0
- data/lib/volt/models/validations/validations.rb +21 -6
- data/lib/volt/models/validators/type_validator.rb +35 -3
- data/lib/volt/page/bindings/content_binding.rb +1 -1
- data/lib/volt/page/bindings/event_binding.rb +40 -16
- data/lib/volt/page/document_events.rb +8 -6
- data/lib/volt/reactive/reactive_array.rb +18 -1
- data/lib/volt/server/forking_server.rb +7 -1
- data/lib/volt/server/html_parser/attribute_scope.rb +26 -0
- data/lib/volt/server/html_parser/component_view_scope.rb +30 -22
- data/lib/volt/server/middleware/default_middleware_stack.rb +6 -1
- data/lib/volt/server/rack/asset_files.rb +5 -3
- data/lib/volt/server/rack/opal_files.rb +35 -23
- data/lib/volt/server/rack/sprockets_helpers_setup.rb +71 -0
- data/lib/volt/server/template_handlers/view_processor.rb +1 -2
- data/lib/volt/utils/promise_extensions.rb +1 -1
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +0 -2
- data/lib/volt/volt/client_setup/browser.rb +11 -0
- data/spec/apps/kitchen_sink/Gemfile +37 -14
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +3 -0
- data/spec/apps/kitchen_sink/app/main/controllers/events_controller.rb +26 -0
- data/spec/apps/kitchen_sink/app/main/views/events/index.html +30 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +3 -0
- data/spec/apps/kitchen_sink/app/main/views/main/yield.html +1 -6
- data/spec/apps/kitchen_sink/app/main/views/{yield-component → yield_component}/index.html +0 -0
- data/spec/extra_core/array_spec.rb +26 -0
- data/spec/integration/bindings_spec.rb +9 -0
- data/spec/integration/event_spec.rb +19 -0
- data/spec/models/array_model_spec.rb +13 -0
- data/spec/models/field_helpers_spec.rb +2 -2
- data/spec/models/validations_spec.rb +31 -0
- data/spec/models/validators/type_validator_spec.rb +47 -1
- data/spec/reactive/reactive_array_spec.rb +46 -0
- data/spec/server/forking_server_spec.rb +27 -0
- data/spec/server/html_parser/view_scope_spec.rb +44 -0
- data/spec/server/rack/asset_files_spec.rb +2 -2
- data/templates/project/Gemfile.tt +8 -0
- data/templates/project/config/app.rb.tt +2 -1
- data/volt.gemspec +1 -1
- metadata +31 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 848470b46efd1f1d8835f8501af6fc39d052cd4c
|
4
|
+
data.tar.gz: 6ff661da03f4f1e572c566b95d2b91868748148e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b26392d7fab2365755625fafd4708cc8398eecf3aad5c83757a3fbdb6f52baa1c9f38f483d23a52ca61ae98e5e42955028e382e87abf524495851d72684644
|
7
|
+
data.tar.gz: fe2f9c21b79e7da0b478b84aaffaa86da7cf63bf73b2f0b793723c73351de40971027c17044907822b43adbc88d3028ed525a0a7a5aca54fa8718068e998b915
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,15 @@
|
|
7
7
|
- Page load performance was improved, and more of sprockets was used for component loading.
|
8
8
|
- You can now return promises in permissions blocks. Also, can_read?, can_create?, and .can_delete?
|
9
9
|
- Anything in /public is now served via Rack::Static in the default middleware stack. (So you can put user uploaded images in there)
|
10
|
+
- You can now use _ or - in volt tag names and attributes. (We're moving to using dash ( - ) as the standard in html)
|
11
|
+
- You can now trigger events on controllers rendered as tags. The events will bubble up through the DOM and can be caught by any e- bindings. See the docs for more information.
|
12
|
+
- Rewrote the precompile pipeline.
|
13
|
+
- Added image compression by default. (using image_optim)
|
14
|
+
- All volt CLI tasks now can run from inside of any directory in the volt app (or the root)
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- fix issue with ```raw``` and promises (#275)
|
18
|
+
- fix issue with .length on store (#269)
|
10
19
|
|
11
20
|
## 0.9.4
|
12
21
|
### Lingo Change
|
@@ -34,6 +43,7 @@ the base collections will now be called "Repositories" or "Repo's" for short. T
|
|
34
43
|
- fixed issue with local_store not persisting in some cases
|
35
44
|
- runners now block until messages have propigated to the message bus and updates have been pushed.
|
36
45
|
- upgraded some dependency gems to fix a conflict
|
46
|
+
- fixed bug with .last on ReactiveArray (#259)
|
37
47
|
|
38
48
|
## 0.9.3
|
39
49
|
[0.9.3 Update Blog Post](http://blog.voltframework.com/post/121128931859/0-9-3-stuff-you-asked-for)
|
data/README.md
CHANGED
@@ -35,11 +35,19 @@ There is also a [work in progress tutorial](https://github.com/rhgraysonii/volt_
|
|
35
35
|
|
36
36
|
# More Videos
|
37
37
|
|
38
|
-
Rick Carlino has been putting together some great volt tutorial videos also.
|
39
|
-
|
40
|
-
- [Volt
|
41
|
-
- [
|
42
|
-
- [
|
38
|
+
Rick Carlino has been putting together some [great volt tutorial videos](http://datamelon.io/blog) also.
|
39
|
+
|
40
|
+
- [Volt URL Routing](http://datamelon.io/blog/2015/routes-and-multi-view-apps.html)
|
41
|
+
- [Volt Tasks](http://datamelon.io/blog/2015/creating-volt-task-objects.html)
|
42
|
+
- [Volt Views](http://datamelon.io/blog/2015/understanding-views-in-volt-with-a-card-game.html)
|
43
|
+
- [Volt Permissions](http://datamelon.io/blog/2015/twitter-clone-demonstrates-volt-permissions.html)
|
44
|
+
- [Volt Runners](http://datamelon.io/blog/2015/automation-of-everything-with-volt-runners.html)
|
45
|
+
- [Volt Components](http://datamelon.io/blog/2015/staying-productive-with-the-volt-component-ecosystem.html)
|
46
|
+
- [REST APIs in Volt](http://datamelon.io/blog/2015/building-rest-apis-with-volt.html)
|
47
|
+
- [Javascript Library Interop](http://datamelon.io/blog/2015/using-js-libraries-with-opal.html)
|
48
|
+
- [Credit Card Payments with Volt](http://datamelon.io/blog/2015/payment-form-using-volt-and-stripe.html)
|
49
|
+
- [Build a Realtime Chat App](http://datamelon.io/blog/2015/building-a-chat-app-in-volt.html)
|
50
|
+
- [6 Key Concepts for New Volt Learners](http://datamelon.io/blog/2015/6-concepts-for-volt-beginners.html)
|
43
51
|
|
44
52
|
@ahnbizcad maintains a [playlist of Volt related videos](https://www.youtube.com/watch?v=McxtO8ybxy8&list=PLmQFeDKFCPXatHb-zEXwfeMH01DPiZjP7).
|
45
53
|
|
File without changes
|
@@ -30,11 +30,14 @@ class LiveQuery
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def notify_added(index, data, skip_channel)
|
33
|
-
# puts "Added: #{index} - #{data.inspect}"
|
34
33
|
# Make model for testing permissions against
|
35
|
-
model =
|
34
|
+
model = nil
|
36
35
|
|
37
36
|
notify! do |channel|
|
37
|
+
# Only load the model for filtering if we are sending to a channel
|
38
|
+
# (skip if we are the only one listening)
|
39
|
+
model ||= model_for_filter(data)
|
40
|
+
|
38
41
|
filtered_data = nil
|
39
42
|
Volt.as_user(channel.user_id) do
|
40
43
|
filtered_data = model.filtered_attributes.sync
|
@@ -52,9 +55,14 @@ class LiveQuery
|
|
52
55
|
end
|
53
56
|
|
54
57
|
def notify_changed(id, data, skip_channel)
|
55
|
-
|
58
|
+
# puts "NOTIFY CHANGED"
|
59
|
+
model = nil
|
56
60
|
|
57
61
|
notify!(skip_channel) do |channel|
|
62
|
+
# Only load the model for filtering if we are sending to a channel
|
63
|
+
# (skip if we are the only one listening)
|
64
|
+
model ||= model_for_filter(data)
|
65
|
+
|
58
66
|
filtered_data = nil
|
59
67
|
Volt.as_user(channel.user_id) do
|
60
68
|
filtered_data = model.filtered_attributes.sync
|
@@ -9,31 +9,21 @@ class StoreTasks < Volt::Task
|
|
9
9
|
model_name = collection.singularize.camelize
|
10
10
|
|
11
11
|
# Fetch the model
|
12
|
-
collection = store.
|
12
|
+
collection = store.get(path[-2])
|
13
13
|
|
14
14
|
# See if the model has already been made
|
15
|
-
collection.where(id: data[:id]).first
|
16
|
-
# Otherwise assign to the collection
|
17
|
-
model ||= collection
|
15
|
+
model_promise = collection.where(id: data[:id]).first
|
18
16
|
|
19
|
-
|
20
|
-
buffer = model.buffer
|
21
|
-
|
22
|
-
# Assign the changed data to the buffer
|
23
|
-
buffer.assign_attributes(data, false, true)
|
24
|
-
|
25
|
-
buffer
|
26
|
-
end
|
17
|
+
return collection, model_promise
|
27
18
|
end
|
28
19
|
|
29
20
|
def save(collection, path, data)
|
30
21
|
data = data.symbolize_keys
|
31
|
-
|
22
|
+
model_promise = nil
|
32
23
|
|
33
|
-
# Don't check the permissions when we load the model, since we want all fields
|
34
24
|
Volt.skip_permissions do
|
35
25
|
Volt::Model.no_validate do
|
36
|
-
|
26
|
+
collection, model_promise = load_model(collection, path, data)
|
37
27
|
end
|
38
28
|
end
|
39
29
|
|
@@ -44,9 +34,16 @@ class StoreTasks < Volt::Task
|
|
44
34
|
# who sent the update.
|
45
35
|
#
|
46
36
|
# return another promise
|
47
|
-
|
37
|
+
model_promise.then do |model|
|
48
38
|
Thread.current['in_channel'] = @channel
|
49
|
-
|
39
|
+
|
40
|
+
result = if model
|
41
|
+
model.update(data)
|
42
|
+
else
|
43
|
+
collection.create(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
save_promise = result.then do |result|
|
50
47
|
next nil
|
51
48
|
end.fail do |err|
|
52
49
|
# An error object, convert to hash
|
data/lib/volt/cli.rb
CHANGED
@@ -131,5 +131,27 @@ end
|
|
131
131
|
# Add in more features
|
132
132
|
require 'volt/cli/asset_compile'
|
133
133
|
|
134
|
+
unless Gem.win_platform?
|
135
|
+
# Change CWD to the root of the volt project
|
136
|
+
pwd = Dir.pwd
|
137
|
+
changed = false
|
138
|
+
loop do
|
139
|
+
if File.exists?(pwd + '/Gemfile')
|
140
|
+
Dir.chdir(pwd) if changed
|
141
|
+
break
|
142
|
+
else
|
143
|
+
changed = true
|
144
|
+
|
145
|
+
# Move up a directory and try again
|
146
|
+
pwd = pwd.gsub(/\/[^\/]+$/, '')
|
147
|
+
|
148
|
+
if pwd == ''
|
149
|
+
puts "You are not currently in a volt project directory"
|
150
|
+
exit 1
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
134
156
|
puts "Volt #{Volt::Version::STRING}"
|
135
157
|
Volt::CLI.start(ARGV)
|
@@ -9,9 +9,11 @@ module Volt
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def compile
|
12
|
-
|
12
|
+
say "Starting Precompile...", :red
|
13
13
|
require 'fileutils'
|
14
14
|
ENV['SERVER'] = 'true'
|
15
|
+
ENV['MAPS'] = 'false'
|
16
|
+
ENV['NO_FORKING'] = 'true'
|
15
17
|
|
16
18
|
require 'opal'
|
17
19
|
require 'rack'
|
@@ -19,90 +21,88 @@ module Volt
|
|
19
21
|
require 'volt/volt/core'
|
20
22
|
require 'volt/boot'
|
21
23
|
require 'volt/server'
|
24
|
+
require 'volt/server/rack/component_paths'
|
25
|
+
require 'volt/server/rack/component_code'
|
22
26
|
|
23
27
|
@root_path ||= Dir.pwd
|
24
28
|
Volt.root = @root_path
|
25
29
|
|
26
|
-
volt_app = Volt.boot(@root_path)
|
27
|
-
|
28
|
-
require 'volt/server/rack/component_paths'
|
29
|
-
require 'volt/server/rack/component_code'
|
30
|
+
@volt_app = Volt.boot(@root_path)
|
30
31
|
|
31
32
|
@app_path = File.expand_path(File.join(@root_path, 'app'))
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
puts 'Compile Opal for components'
|
39
|
-
write_component_js
|
40
|
-
puts 'Copy assets'
|
41
|
-
write_sprockets
|
42
|
-
puts 'Compile JS/CSS'
|
43
|
-
write_js_and_css
|
44
|
-
puts 'Write index files'
|
34
|
+
say 'Compiling RB, JS, CSS, and Images...', :red
|
35
|
+
write_files_and_manifest
|
36
|
+
compile_manifests
|
37
|
+
say 'Write index files...', :red
|
45
38
|
write_index
|
46
|
-
|
47
|
-
puts "compiled"
|
48
|
-
end
|
49
|
-
|
50
|
-
def logical_paths_and_full_paths
|
51
|
-
env = @opal_files.environment
|
52
|
-
env.each_file do |full_path|
|
53
|
-
# logical_path = env[full_path].logical_path
|
54
|
-
# logical_path = @opal_files.environment.send(:logical_path_for_filename, full_path, []).to_s
|
55
|
-
# puts "FULL PATH: #{full_path.inspect} -- #{logical_path}"
|
56
|
-
|
57
|
-
# yield(logical_path, full_path.to_s)
|
58
|
-
end
|
59
|
-
|
39
|
+
say "Done", :green
|
60
40
|
end
|
61
41
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
42
|
+
def write_files_and_manifest
|
43
|
+
asset_files = AssetFiles.from_cache('main', @volt_app.component_paths)
|
44
|
+
# Write a temp css file
|
45
|
+
js = asset_files.javascript(@volt_app)
|
46
|
+
css = asset_files.css
|
47
|
+
@tmp_files = []
|
48
|
+
|
49
|
+
File.open(Volt.root + '/app/main/app.js', 'wb') do |file|
|
50
|
+
js.each do |type, src_or_body|
|
51
|
+
if type == :src
|
52
|
+
src = src_or_body
|
53
|
+
url = src.gsub(/^\/assets\//, '')
|
54
|
+
file.write("//= require '#{url}'\n")
|
55
|
+
else
|
56
|
+
body = src_or_body
|
57
|
+
|
58
|
+
# Write to a tempfile, since sprockets can't mix requires and
|
59
|
+
# code.
|
60
|
+
|
61
|
+
require 'securerandom'
|
62
|
+
hex = SecureRandom.hex
|
63
|
+
tmp_path = Volt.root + "/app/main/__#{hex}.js"
|
64
|
+
url = "main/__#{hex}"
|
65
|
+
file.write("//= require '#{url}'\n")
|
66
|
+
|
67
|
+
@tmp_files << tmp_path
|
68
|
+
File.open(tmp_path, 'wb') {|f| f.write("#{body}\n") }
|
69
|
+
end
|
71
70
|
end
|
72
71
|
end
|
73
|
-
end
|
74
72
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
write_sprocket_file(logical_path)
|
73
|
+
File.open(Volt.root + '/app/main/app.scss', 'wb') do |file|
|
74
|
+
css.each do |link|
|
75
|
+
url = link.gsub(/^\/assets\//, '')
|
76
|
+
file.write("//= require '#{url}'\n")
|
80
77
|
end
|
81
78
|
end
|
82
79
|
end
|
83
80
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
begin
|
88
|
-
# Only write out the assets
|
89
|
-
# if logical_path =~ /\/assets\//
|
90
|
-
content = @opal_files.environment[logical_path].to_s
|
91
|
-
write_file(path, content)
|
92
|
-
# end
|
93
|
-
rescue Sprockets::FileNotFound, SyntaxError => e
|
94
|
-
# ignore
|
95
|
-
end
|
96
|
-
end
|
81
|
+
def compile_manifests
|
82
|
+
manifest = Sprockets::Manifest.new(@volt_app.sprockets, './public/assets/manifest.json')
|
97
83
|
|
98
|
-
|
99
|
-
|
84
|
+
# Compile the files (and linked assets)
|
85
|
+
manifest.compile('main/app.js')
|
86
|
+
manifest.compile('main/app.css')
|
87
|
+
|
88
|
+
# Clear temp files
|
89
|
+
@tmp_files.each {|path| FileUtils.rm(path) }
|
90
|
+
|
91
|
+
# Remove the temp files
|
92
|
+
FileUtils.rm(Volt.root + '/app/main/app.js')
|
93
|
+
FileUtils.rm(Volt.root + '/app/main/app.scss')
|
100
94
|
end
|
101
95
|
|
102
96
|
def write_index
|
103
|
-
|
97
|
+
require 'volt/cli/base_index_renderer'
|
98
|
+
|
99
|
+
output_path = "#{@root_path}/public/index.html"
|
100
|
+
require 'json'
|
101
|
+
|
102
|
+
@manifest = JSON.parse(File.read(@root_path + '/public/assets/manifest.json'))
|
103
|
+
output_html = BaseIndexRenderer.new(@manifest).html
|
104
104
|
|
105
|
-
write_file(
|
105
|
+
write_file(output_path, output_html)
|
106
106
|
end
|
107
107
|
|
108
108
|
def write_file(path, data)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Render the config/base/index.html when precompiling. Here we only render
|
2
|
+
# one js and one css file.
|
3
|
+
|
4
|
+
module Volt
|
5
|
+
class BaseIndexRenderer
|
6
|
+
def initialize(manifest)
|
7
|
+
@manifest = manifest
|
8
|
+
end
|
9
|
+
|
10
|
+
def html
|
11
|
+
index_path = File.expand_path(File.join(Volt.root, 'config/base/index.html'))
|
12
|
+
html = File.read(index_path)
|
13
|
+
|
14
|
+
ERB.new(html, nil, '-').result(binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
# When writing the index, we render the
|
18
|
+
def javascript_tags
|
19
|
+
"<script src=\"/assets/#{@manifest['assets']['main/app.js']}\"></script>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def css_tags
|
23
|
+
"<link href=\"/assets/#{@manifest['assets']['main/app.css']}\" media=\"all\" rel=\"stylesheet\" type=\"text/css\" />"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/volt/cli/generate.rb
CHANGED
@@ -81,7 +81,7 @@ class Generate < Thor
|
|
81
81
|
method_option :name, type: :string, banner: 'The name of the task.'
|
82
82
|
method_option :component, type: :string, default: 'main', banner: 'The component the task should be created in.', required: false
|
83
83
|
def task(name, component = 'main')
|
84
|
-
name = name.underscore.gsub(/_tasks$/, '').singularize + '_task'
|
84
|
+
name = name.underscore.gsub(/_tasks$/, '').singularize.gsub('_task', '') + '_task'
|
85
85
|
output_file = Dir.pwd + "/app/#{component}/tasks/#{name}.rb"
|
86
86
|
spec_file = Dir.pwd + "/spec/app/#{component}/tasks/#{name}_spec.rb"
|
87
87
|
template('task/task.rb.tt', output_file, task_name: name.camelize.singularize)
|
data/lib/volt/config.rb
CHANGED
@@ -27,16 +27,19 @@ module Volt
|
|
27
27
|
|
28
28
|
# Container returns the node that is parent to all nodes in the section.
|
29
29
|
def container
|
30
|
+
check_section!('container')
|
30
31
|
section.container_node
|
31
32
|
end
|
32
33
|
|
33
34
|
def dom_nodes
|
35
|
+
check_section!('dom_nodes')
|
34
36
|
section.range
|
35
37
|
end
|
36
38
|
|
37
39
|
# Walks the dom_nodes range until it finds an element. Typically this will
|
38
40
|
# be the container element without the whitespace text nodes.
|
39
41
|
def first_element
|
42
|
+
check_section!('first_element')
|
40
43
|
range = dom_nodes
|
41
44
|
nodes = `range.startContainer.childNodes`
|
42
45
|
|
@@ -76,6 +79,24 @@ module Volt
|
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
82
|
+
def trigger(event, *args)
|
83
|
+
# Trigger on the current controller if an e- was setup on the component.
|
84
|
+
component_event = attrs.send(:"e_#{event}")
|
85
|
+
|
86
|
+
if component_event
|
87
|
+
# Add a nil arg for the event, trim to arity
|
88
|
+
args2 = (args + [nil])[0...component_event.arity]
|
89
|
+
component_event.call(*args2)
|
90
|
+
end
|
91
|
+
|
92
|
+
args.unshift(self)
|
93
|
+
# Trigger via jquery, so it bubbles up through the DOM
|
94
|
+
`$(#{first_element}).trigger(#{event}, #{args});`
|
95
|
+
|
96
|
+
# return nil, so we return a ruby object
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
79
100
|
def self.model(val)
|
80
101
|
self.default_model = val
|
81
102
|
end
|
@@ -208,7 +229,14 @@ module Volt
|
|
208
229
|
# Raw marks a string as html safe, so bindings can be rendered as html.
|
209
230
|
# With great power comes great responsibility.
|
210
231
|
def raw(str)
|
211
|
-
|
232
|
+
# Promises need to have .to_s called using .then, since .to_s is a promise
|
233
|
+
# method, so it won't be passed down to the value.
|
234
|
+
if str.is_a?(Promise)
|
235
|
+
str = str.then(&:to_s)
|
236
|
+
else
|
237
|
+
str = str.to_s unless str.is_a?(String)
|
238
|
+
end
|
239
|
+
|
212
240
|
str.html_safe
|
213
241
|
end
|
214
242
|
|
@@ -230,5 +258,13 @@ module Volt
|
|
230
258
|
super
|
231
259
|
end
|
232
260
|
end
|
261
|
+
|
262
|
+
private
|
263
|
+
def check_section!(method_name)
|
264
|
+
unless section
|
265
|
+
raise "##{method_name} can't be called before the {action}_ready method is called"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
233
269
|
end
|
234
270
|
end
|