volt 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +37 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/Rakefile +23 -0
- data/Readme.md +34 -0
- data/VERSION +1 -0
- data/bin/volt +4 -0
- data/docs/GETTING_STARTED.md +7 -0
- data/docs/GUIDE.md +33 -0
- data/lib/volt.rb +15 -0
- data/lib/volt/benchmark/benchmark.rb +25 -0
- data/lib/volt/cli.rb +34 -0
- data/lib/volt/console.rb +19 -0
- data/lib/volt/controllers/model_controller.rb +29 -0
- data/lib/volt/extra_core/array.rb +10 -0
- data/lib/volt/extra_core/blank.rb +88 -0
- data/lib/volt/extra_core/extra_core.rb +7 -0
- data/lib/volt/extra_core/numeric.rb +9 -0
- data/lib/volt/extra_core/object.rb +36 -0
- data/lib/volt/extra_core/string.rb +29 -0
- data/lib/volt/extra_core/stringify_keys.rb +7 -0
- data/lib/volt/extra_core/true_false.rb +44 -0
- data/lib/volt/extra_core/try.rb +31 -0
- data/lib/volt/models.rb +5 -0
- data/lib/volt/models/array_model.rb +37 -0
- data/lib/volt/models/model.rb +210 -0
- data/lib/volt/models/model_wrapper.rb +23 -0
- data/lib/volt/models/params.rb +67 -0
- data/lib/volt/models/url.rb +192 -0
- data/lib/volt/page/url_tracker.rb +36 -0
- data/lib/volt/reactive/array_extensions.rb +13 -0
- data/lib/volt/reactive/event_chain.rb +126 -0
- data/lib/volt/reactive/events.rb +283 -0
- data/lib/volt/reactive/object_tracker.rb +99 -0
- data/lib/volt/reactive/object_tracking.rb +15 -0
- data/lib/volt/reactive/reactive_array.rb +222 -0
- data/lib/volt/reactive/reactive_tags.rb +64 -0
- data/lib/volt/reactive/reactive_value.rb +368 -0
- data/lib/volt/reactive/string_extensions.rb +34 -0
- data/lib/volt/router/routes.rb +83 -0
- data/lib/volt/server.rb +121 -0
- data/lib/volt/server/binding_setup.rb +2 -0
- data/lib/volt/server/channel_handler.rb +31 -0
- data/lib/volt/server/component_handler.rb +88 -0
- data/lib/volt/server/if_binding_setup.rb +29 -0
- data/lib/volt/server/request_handler.rb +16 -0
- data/lib/volt/server/scope.rb +43 -0
- data/lib/volt/server/source_map_server.rb +31 -0
- data/lib/volt/server/template_parser.rb +452 -0
- data/lib/volt/store/mongo.rb +5 -0
- data/lib/volt/templates/attribute_binding.rb +110 -0
- data/lib/volt/templates/base_binding.rb +37 -0
- data/lib/volt/templates/channel.rb +48 -0
- data/lib/volt/templates/content_binding.rb +35 -0
- data/lib/volt/templates/document_events.rb +80 -0
- data/lib/volt/templates/each_binding.rb +115 -0
- data/lib/volt/templates/event_binding.rb +51 -0
- data/lib/volt/templates/if_binding.rb +74 -0
- data/lib/volt/templates/memory_test.rb +26 -0
- data/lib/volt/templates/page.rb +146 -0
- data/lib/volt/templates/reactive_template.rb +38 -0
- data/lib/volt/templates/render_queue.rb +5 -0
- data/lib/volt/templates/sub_context.rb +23 -0
- data/lib/volt/templates/targets/attribute_section.rb +33 -0
- data/lib/volt/templates/targets/attribute_target.rb +18 -0
- data/lib/volt/templates/targets/base_section.rb +14 -0
- data/lib/volt/templates/targets/binding_document/base_node.rb +3 -0
- data/lib/volt/templates/targets/binding_document/component_node.rb +112 -0
- data/lib/volt/templates/targets/binding_document/html_node.rb +11 -0
- data/lib/volt/templates/targets/dom_section.rb +147 -0
- data/lib/volt/templates/targets/dom_target.rb +11 -0
- data/lib/volt/templates/template_binding.rb +159 -0
- data/lib/volt/templates/template_renderer.rb +50 -0
- data/spec/models/event_chain_spec.rb +129 -0
- data/spec/models/model_spec.rb +340 -0
- data/spec/models/old_model_spec.rb +109 -0
- data/spec/models/reactive_array_spec.rb +262 -0
- data/spec/models/reactive_tags_spec.rb +35 -0
- data/spec/models/reactive_value_spec.rb +336 -0
- data/spec/models/string_extensions_spec.rb +57 -0
- data/spec/router/routes_spec.rb +24 -0
- data/spec/server/template_parser_spec.rb +50 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/store/mongo_spec.rb +4 -0
- data/spec/templates/targets/binding_document/component_node_spec.rb +18 -0
- data/spec/templates/template_binding_spec.rb +98 -0
- data/templates/.gitignore +12 -0
- data/templates/Gemfile.tt +8 -0
- data/templates/app/.empty_directory +0 -0
- data/templates/app/home/config/routes.rb +1 -0
- data/templates/app/home/controllers/index_controller.rb +5 -0
- data/templates/app/home/css/.empty_directory +0 -0
- data/templates/app/home/models/.empty_directory +0 -0
- data/templates/app/home/views/index/about.html +9 -0
- data/templates/app/home/views/index/home.html +7 -0
- data/templates/app/home/views/index/index.html +28 -0
- data/templates/config.ru +4 -0
- data/templates/public/css/ansi.css +0 -0
- data/templates/public/css/bootstrap-theme.css +459 -0
- data/templates/public/css/bootstrap.css +7098 -0
- data/templates/public/css/jumbotron.css +79 -0
- data/templates/public/fonts/glyphicons-halflings-regular.eot +0 -0
- data/templates/public/fonts/glyphicons-halflings-regular.svg +229 -0
- data/templates/public/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/templates/public/fonts/glyphicons-halflings-regular.woff +0 -0
- data/templates/public/index.html +25 -0
- data/templates/public/js/bootstrap.js +0 -0
- data/templates/public/js/jquery-2.0.3.js +8829 -0
- data/templates/public/js/sockjs-0.2.1.min.js +27 -0
- data/templates/spec/spec_helper.rb +20 -0
- data/volt.gemspec +41 -0
- metadata +412 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f31285f8d34376239bed9e92cb9dec093f8331e
|
4
|
+
data.tar.gz: 9fe3e6d4e61cf93734a72fd92f41df30ffc672f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 098e047b75cf968bdd84634d5b1262600678f2765c73e759d5e5f4fb94503b20485ca1146fcf23fd0e039aee9fc186240c9dbfef732ac567deeed68463b04b03
|
7
|
+
data.tar.gz: 3ef0821f1ec5f15e02d174f6016f2a83a2d9f2c482d805c2baacfdba972b647f69345261bcedd13c9a1763eed7a21fa3df6f2f83c95bbd2185052d45fffbf00e
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.idea
|
19
|
+
.yardoc
|
20
|
+
.sass-cache
|
21
|
+
.DS_Store
|
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.0
|
data/Gemfile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# gem 'rspec', '3.0.0.beta1'
|
6
|
+
# gem 'nokogiri', :require => false
|
7
|
+
gem 'opal', git: 'https://github.com/opal/opal.git'
|
8
|
+
gem 'opal-jquery', :git => 'https://github.com/opal/opal-jquery.git'
|
9
|
+
gem 'sockjs', git: 'https://github.com/kacperk/sockjs-ruby.git', require: false, platforms: :mri
|
10
|
+
|
11
|
+
# gem 'thor'
|
12
|
+
|
13
|
+
# gem 'rack'
|
14
|
+
# gem 'sprockets'
|
15
|
+
# gem 'sprockets-sass'
|
16
|
+
# gem 'sass'
|
17
|
+
|
18
|
+
# gem 'mongo', require: false
|
19
|
+
# gem 'pry', require: false
|
20
|
+
# gem 'thin', require: false, platforms: :mri
|
21
|
+
|
22
|
+
# Json parsing with multi_json, et al
|
23
|
+
# gem 'multi_json'
|
24
|
+
# gem 'oj', :platforms => :mri, :require => false
|
25
|
+
# gem 'jrjackson', :platforms => :jruby, :require => false
|
26
|
+
|
27
|
+
# gem 'rake', '10.0.4'
|
28
|
+
|
29
|
+
# # Needed to get opal to work on rbx
|
30
|
+
# gem 'racc', platforms: :rbx
|
31
|
+
|
32
|
+
group :development do
|
33
|
+
# gem 'guard', '2.0.1' # bug in current guard
|
34
|
+
# gem 'guard-rspec'
|
35
|
+
# gem 'opal-rspec', '0.3.0.beta2'#, git: 'https://github.com/adambeynon/opal-rspec.git'
|
36
|
+
# gem 'yard', require: false
|
37
|
+
end
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ryan Stout
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
Bundler.require(:development)
|
5
|
+
|
6
|
+
|
7
|
+
task :docs do
|
8
|
+
`bundle exec yardoc 'lib/**/*.rb' - Readme.md docs/*`
|
9
|
+
# require 'yard'
|
10
|
+
# require 'yard-docco'
|
11
|
+
#
|
12
|
+
# YARD::Rake::YardocTask.new do |t|
|
13
|
+
# t.files = ['lib/**/*.rb']
|
14
|
+
# # t.options = ['--any', '--extra', '--opts'] # optional
|
15
|
+
# end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Add our opal/ directory to the load path
|
20
|
+
Opal.append_path(File.expand_path('../lib', __FILE__))
|
21
|
+
|
22
|
+
require 'opal/rspec/rake_task'
|
23
|
+
Opal::RSpec::RakeTask.new(:default)
|
data/Readme.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Volt
|
2
|
+
|
3
|
+
NOTE: VOLT IS STILL IN DEVELOPMENT, DON'T USE IT FOR ANYTHING SERIOUS YET
|
4
|
+
|
5
|
+
Volt is a ruby web framework where your ruby code runs on both the server and the client (via [opal](https://github.com/opal/opal).) The dom automatically update as the user interacts with the page. Page state can be stored in the url, if the user hits a url directly, the HTML will first be rendered on the server for faster load times and easier indexing by search engines.
|
6
|
+
|
7
|
+
Instead of syncing data between the client and server via HTTP, volt uses a persistent connection between the client and server. When data updated on one client, it is updated in the database and any other listening clients. (With almost no setup code needed)
|
8
|
+
|
9
|
+
Pages HTML is written in a handlebars like template language. Volt uses data flow/reactive programming to automatically and intellegently propigate changes to the dom (or anything other code wanting to know when a value updates) When something in the dom changes, Volt intellegent updates only the nodes that need to be changed.
|
10
|
+
|
11
|
+
## Goals
|
12
|
+
|
13
|
+
Volt has the following goals:
|
14
|
+
|
15
|
+
1. Developer happieness
|
16
|
+
2. Write once on the client and the server
|
17
|
+
3. Automatic data syncing between client and server
|
18
|
+
4. Apps are built as nested components. Components can be shared (via gems)
|
19
|
+
5. Concurrent. Volt provides tools to simplify concurrency. Component rendering is done in parallel on the server.
|
20
|
+
6. Intellegent asset management
|
21
|
+
7. Secure (shouldn't need to be said, but it does)
|
22
|
+
8. Be fast/light
|
23
|
+
9. Understandable code base
|
24
|
+
10. Component Upgradeability
|
25
|
+
|
26
|
+
## 10. Component Upgradeability
|
27
|
+
|
28
|
+
(seamless promotion)
|
29
|
+
Everyone wishes that we could predict the scope and required features for each part of our application, but in the real world, things we don't expect to grow large often do and things we think will be large don't end up that way. Volt provides an easy way to promote sections of html and code to provide more
|
30
|
+
|
31
|
+
- subtemplate
|
32
|
+
- template
|
33
|
+
- controller
|
34
|
+
- component
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.3
|
data/bin/volt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Getting Started
|
2
|
+
|
3
|
+
Volt relies on a few concepts to take make web development faster and easier. The first of these is reactive programming. Data on the front and back end is stored in models. Instead of manually updating a page when the data changes, the page is coded using a handlebars like templating language which automatically updates when the data changes.
|
4
|
+
|
5
|
+
## Reactive Values
|
6
|
+
|
7
|
+
The key to making these updates happen is something we call "Reactive Values." A ReactiveValue wraps another v
|
data/docs/GUIDE.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# VOLT guide
|
2
|
+
|
3
|
+
This guide will take you through creating a basic web application in Volt. This tutorial assumes a basic knowledge of ruby and web development.
|
4
|
+
|
5
|
+
To get started, install volt:
|
6
|
+
|
7
|
+
gem install voltframework
|
8
|
+
|
9
|
+
Then create a new project:
|
10
|
+
|
11
|
+
volt new project_name
|
12
|
+
|
13
|
+
This will setup a basic project. Now lets run the server.
|
14
|
+
|
15
|
+
volt server
|
16
|
+
|
17
|
+
|
18
|
+
## Bindings
|
19
|
+
|
20
|
+
When a user interacts with a web page, typically we want to do two things:
|
21
|
+
|
22
|
+
1) Change application state
|
23
|
+
2) Update the DOM
|
24
|
+
|
25
|
+
For example when a user clicks to add a new todo item to a todo list, we might create a JavaScript object to represent the todo item, then add an item to the list's DOM. A lot of work needs to be done to make sure that the JavaScript object and the DOM always stay in sync.
|
26
|
+
|
27
|
+
Recently the idea of "reactive programming" has been used to simplify maintaining the DOM. The idea is instead of having event handlers that manage a model (or JavaScript object) and manage the DOM, we have event handlers that manage reactive data models. We describe our DOM layer in a declaritive way so that it automatically knows how to render our data models.
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
## Components
|
32
|
+
|
33
|
+
Apps are broken up into components. Each folder under app/ represents a component. You can think of components like a single page app. When a page within a component is loaded, all the controllers, models, and views within a component are loaded on the front end. The initial page load will be rendered on the backend for quick loading, then any future updates will be rendered on the front end.
|
data/lib/volt.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Benchmark
|
2
|
+
def self.bm(iterations=1)
|
3
|
+
puts "BM"
|
4
|
+
|
5
|
+
times = []
|
6
|
+
total_time = nil
|
7
|
+
result = nil
|
8
|
+
|
9
|
+
iterations.times do
|
10
|
+
start_time = `Date.now()`
|
11
|
+
result = yield
|
12
|
+
end_time = `Date.now()`
|
13
|
+
total_time = `end_time - start_time`
|
14
|
+
times << total_time
|
15
|
+
end
|
16
|
+
|
17
|
+
if iterations == 1
|
18
|
+
puts "TOTAL TIME: #{total_time}ms"
|
19
|
+
else
|
20
|
+
puts "Times: #{times.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
return result
|
24
|
+
end
|
25
|
+
end
|
data/lib/volt/cli.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
class CLI < Thor
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
desc "new PROJECT_NAME", "generates a new project."
|
8
|
+
def new(name)
|
9
|
+
directory(".", name)
|
10
|
+
|
11
|
+
say "Bundling Gems...."
|
12
|
+
`cd #{name} ; bundle`
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "console", "run the console on the project in the current directory"
|
16
|
+
def console
|
17
|
+
require 'volt/console'
|
18
|
+
Console.start
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "server", "run the server on the project in the current directory"
|
22
|
+
def server
|
23
|
+
require 'thin'
|
24
|
+
|
25
|
+
ENV['SERVER'] = 'true'
|
26
|
+
Thin::Runner.new(['start']).run!
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.source_root
|
30
|
+
File.expand_path(File.join(File.dirname(__FILE__), '../../templates'))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
CLI.start(ARGV)
|
data/lib/volt/console.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Console
|
2
|
+
def self.start
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
$LOAD_PATH << 'lib'
|
6
|
+
ENV['SERVER'] = 'true'
|
7
|
+
|
8
|
+
require 'volt/extra_core/extra_core'
|
9
|
+
require 'volt/models'
|
10
|
+
require 'volt/models/params'
|
11
|
+
require 'volt/server/template_parser'
|
12
|
+
require 'volt'
|
13
|
+
|
14
|
+
Pry.config.prompt_name = 'volt'
|
15
|
+
|
16
|
+
# start a REPL session
|
17
|
+
Pry.start
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ModelController
|
2
|
+
def initialize(model=nil)
|
3
|
+
@model = model
|
4
|
+
end
|
5
|
+
|
6
|
+
def page
|
7
|
+
$page.page
|
8
|
+
end
|
9
|
+
|
10
|
+
def store
|
11
|
+
$page.store
|
12
|
+
end
|
13
|
+
|
14
|
+
def params
|
15
|
+
$page.params
|
16
|
+
end
|
17
|
+
|
18
|
+
def url
|
19
|
+
$page.url
|
20
|
+
end
|
21
|
+
|
22
|
+
def controller
|
23
|
+
@controller ||= ReactiveValue.new(Model.new)
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method_name, *args, &block)
|
27
|
+
return @model.send(method_name, *args, &block)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class Object
|
2
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
3
|
+
# For example, '', ' ', +nil+, [], and {} are all blank.
|
4
|
+
#
|
5
|
+
# This simplifies:
|
6
|
+
#
|
7
|
+
# if address.nil? || address.empty?
|
8
|
+
#
|
9
|
+
# ...to:
|
10
|
+
#
|
11
|
+
# if address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
|
16
|
+
# An object is present if it's not <tt>blank?</tt>.
|
17
|
+
def present?
|
18
|
+
!blank?
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class NilClass
|
24
|
+
# +nil+ is blank:
|
25
|
+
#
|
26
|
+
# nil.blank? # => true
|
27
|
+
def blank?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class FalseClass
|
33
|
+
# +false+ is blank:
|
34
|
+
#
|
35
|
+
# false.blank? # => true
|
36
|
+
def blank?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class TrueClass
|
42
|
+
# +true+ is not blank:
|
43
|
+
#
|
44
|
+
# true.blank? # => false
|
45
|
+
def blank?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Array
|
51
|
+
# An array is blank if it's empty:
|
52
|
+
#
|
53
|
+
# [].blank? # => true
|
54
|
+
# [1,2,3].blank? # => false
|
55
|
+
alias_method :blank?, :empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
class Hash
|
59
|
+
# A hash is blank if it's empty:
|
60
|
+
#
|
61
|
+
# {}.blank? # => true
|
62
|
+
# { key: 'value' }.blank? # => false
|
63
|
+
alias_method :blank?, :empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
class String
|
67
|
+
# A string is blank if it's empty or contains whitespaces only:
|
68
|
+
#
|
69
|
+
# ''.blank? # => true
|
70
|
+
# ' '.blank? # => true
|
71
|
+
# ' '.blank? # => true
|
72
|
+
# ' something here '.blank? # => false
|
73
|
+
def blank?
|
74
|
+
# self !~ /[^[:space:]]/
|
75
|
+
# TODO: Opal fails with the previous regex
|
76
|
+
self.strip == ''
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Numeric #:nodoc:
|
81
|
+
# No number is blank:
|
82
|
+
#
|
83
|
+
# 1.blank? # => false
|
84
|
+
# 0.blank? # => false
|
85
|
+
def blank?
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|