ice 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +18 -0
- data/{LICENSE → MIT-LICENSE} +1 -1
- data/README.markdown +49 -77
- data/Rakefile +21 -34
- data/lib/ice.rb +8 -4
- data/lib/ice/base_cube.rb +32 -2
- data/lib/ice/cube_helpers.rb +29 -0
- data/lib/ice/cubeable.rb +12 -12
- data/lib/ice/eco_template/base.rb +17 -0
- data/lib/ice/eco_template/context.rb +76 -0
- data/lib/ice/eco_template/handler.rb +30 -0
- data/lib/ice/railtie.rb +6 -10
- metadata +22 -79
- data/.gitignore +0 -23
- data/.specification +0 -135
- data/VERSION +0 -1
- data/ice.gemspec +0 -87
- data/ice_js/History.md +0 -5
- data/ice_js/Readme.md +0 -29
- data/ice_js/lib/form_tag_inputs.js +0 -91
- data/ice_js/lib/path_helper.js +0 -49
- data/ice_js/spec/commands/example_command.rb +0 -19
- data/ice_js/spec/dom.html +0 -23
- data/ice_js/spec/node.js +0 -10
- data/ice_js/spec/rhino.js +0 -10
- data/ice_js/spec/server.html +0 -18
- data/ice_js/spec/server.rb +0 -4
- data/ice_js/spec/support/js.jar +0 -0
- data/ice_js/spec/unit/spec.helper.js +0 -0
- data/ice_js/spec/unit/spec.js +0 -180
- data/init.rb +0 -6
- data/lib/extras/ice_view.rb +0 -166
- data/lib/ice/base.rb +0 -50
- data/lib/parser.js +0 -320
- data/spec/base_cube_spec.rb +0 -45
- data/spec/cube_spec.rb +0 -119
- data/spec/ice_spec.rb +0 -97
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -12
- data/togo +0 -60
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "rails", "3.0.7"
|
4
|
+
gem 'rake', '0.8.7'
|
5
|
+
gem "capybara", ">= 0.4.0"
|
6
|
+
gem "sqlite3"
|
7
|
+
|
8
|
+
gem "rspec-rails", ">= 2.0.0.beta"
|
9
|
+
|
10
|
+
gem "therubyracer"
|
11
|
+
gem "informal"
|
12
|
+
|
13
|
+
gem "jasmine"
|
14
|
+
|
15
|
+
gem "eco"
|
16
|
+
# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
|
17
|
+
# gem 'ruby-debug'
|
18
|
+
# gem 'ruby-debug19'
|
data/{LICENSE → MIT-LICENSE}
RENAMED
data/README.markdown
CHANGED
@@ -1,54 +1,43 @@
|
|
1
|
-
#
|
1
|
+
#Ice Ice Baby!!!
|
2
2
|
|
3
|
-
The Ice
|
3
|
+
The Ice system for CoffeeScript/Javascript templating allows people to serve Javascript templates thanks to [The Ruby Racer](http://github.com/cowboyd/therubyracer), a gem letting you use Google's V8 Javascript engine. These templates are then compiled and served to the browser.
|
4
4
|
|
5
|
-
|
5
|
+
One of the key advantages of this approach is that the templates execute in their own sandbox. This is the approach taken by [Liquid](http://github.com/tobi/liquid) and some of the other template systems.
|
6
6
|
|
7
|
-
|
7
|
+
The template parser we currently use is Eco (written by [Sam Stephenson](https://github.com/sstephenson/eco)). This allows you to use Coffeescript with HTML in an ERB-ish fashion.
|
8
|
+
|
9
|
+
You can then write Eco templates like:
|
8
10
|
|
9
11
|
<table>
|
10
12
|
<tr><th>Name</th><th>Email</th></tr>
|
11
|
-
<% for
|
13
|
+
<% for user in @users %>
|
12
14
|
<tr>
|
13
|
-
<td><%= user.name %></td><td><%=
|
15
|
+
<td><%= user.name %></td><td><%= @mailTo(user.email) %></td>
|
14
16
|
</tr>
|
15
|
-
<%
|
17
|
+
<% end %>
|
16
18
|
</table>
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
Ice.convert_template(template_text, vars = {})
|
21
|
-
|
22
|
-
## Why another templating engine when there is Liquid?
|
23
|
-
|
24
|
-
[Liquid](http://github.com/tobi/liquid) is excellent but it showing its age in a few ways:
|
20
|
+
Eco-formatted files may also exist in your filesystem, provided they have a .eco extension. Also, the templates may be compiled on demand with the method:
|
25
21
|
|
26
|
-
|
27
|
-
* Introduces yet-another-language, whereas many designers/developers are already familiar with javascript
|
28
|
-
* Doesn't allow template creators to use a rich object model and easily create their own functions
|
29
|
-
* Doesn't have a rich set of support libraries like what javascript brings to the table
|
30
|
-
|
31
|
-
Note that we're still big fans of Liquid. In fact, we call this project "Ice" as a tribute (extending the metaphor, we use "Cubes" where they have "Drops").
|
32
|
-
|
33
|
-
In addition, our ice_view.rb file is almost directly ripped out of the liquid project.
|
22
|
+
Ice::EcoTemplate.convert(template_text, vars = {})
|
34
23
|
|
35
24
|
## Installation
|
36
25
|
|
37
|
-
Ice is
|
26
|
+
Ice is currently being developed only for Rails 3. Simply add to your Gemfile
|
38
27
|
|
39
28
|
gem 'ice'
|
40
29
|
|
41
30
|
## to_ice
|
42
31
|
|
43
|
-
Every object is revealed to the templates via its to_ice method. This helps
|
32
|
+
Every object is revealed to the templates via its to_ice method. This helps sanitize the objects that are passed into Ice, so people editing the template only have access to a limited subset of the data.
|
44
33
|
|
45
34
|
Instances of some classes like String and Numeric just return themselves as the result of to_ice. Hashes and Arrays run to_ice recursively on their members.
|
46
35
|
|
47
|
-
If you want an object to map to a different representation, simply define a to_ice object that returns whatever object you want to represent it within the
|
36
|
+
If you want an object to map to a different representation, simply define a to_ice object that returns whatever object you want to represent it within the eco template. These objects are referred to as "Cubes", and are equivalent to "Drops" for those used to the Liquid template.
|
48
37
|
|
49
|
-
##
|
38
|
+
## ActiveModel and to_ice
|
50
39
|
|
51
|
-
To make life easy, since most complex objects passed to the templates will be
|
40
|
+
To make life easy, since most complex objects passed to the templates will be classes including ActiveModel::Serializable, the default to_ice behaviour of these classes is to pass itself in to a class with the same name, but followed by the word "Cube".
|
52
41
|
|
53
42
|
Therefore calling to_ice on instance of a User class will invoke
|
54
43
|
|
@@ -56,7 +45,7 @@ Therefore calling to_ice on instance of a User class will invoke
|
|
56
45
|
|
57
46
|
## BaseCube Class
|
58
47
|
|
59
|
-
|
48
|
+
You can have your cubes inherit from our Ice::BaseCube class. Your cubes inheriting from it can then determine what additional attributes they want to reveal. For example
|
60
49
|
|
61
50
|
class BookCube < Ice::BaseCube
|
62
51
|
revealing :title, :author_id, :genre_id
|
@@ -66,7 +55,7 @@ In order for everything to work easily, you can have your cubes inherit from our
|
|
66
55
|
end
|
67
56
|
end
|
68
57
|
|
69
|
-
would provide a cube with access to the title, author_id and genre properties of the underlying
|
58
|
+
would provide a cube with access to the title, author_id and genre properties of the underlying ActiveModel. In addition, it exposes a reviewer_names function that uses the @source instance variable to get at the record which is being filtered. Note that if no call to `revealing` occurs, the cube generates a mapping for the `@source` object's serializable `attributes`.
|
70
59
|
|
71
60
|
These cubes also have simple belongs_to and has_many associations, so you can write things like:
|
72
61
|
|
@@ -79,15 +68,18 @@ This generates association helper functions such as comment_ids, num_comments, h
|
|
79
68
|
|
80
69
|
Note that the results of all associations and revealed functions are also sanitized via to_ice.
|
81
70
|
|
71
|
+
## Partials
|
72
|
+
|
73
|
+
Partials may now be written in Eco, and included in Erb (and other) templates.
|
74
|
+
|
82
75
|
## NavBar
|
83
76
|
|
84
|
-
To make it easier to generate links, we added a
|
77
|
+
To make it easier to generate links, we added a `@navBar` helper.
|
85
78
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
<%= nav.close() %>
|
79
|
+
<%- @navBar (bar) => %>
|
80
|
+
<%- bar.linkTo("Bar", "/foo") %>
|
81
|
+
<%- bar.linkTo("http://ludicast.com") %>
|
82
|
+
<% end %>
|
91
83
|
|
92
84
|
This then generates the following html
|
93
85
|
|
@@ -96,59 +88,37 @@ This then generates the following html
|
|
96
88
|
<li><a href="http://ludicast.com">http://ludicast.com</a></li>
|
97
89
|
</ul>
|
98
90
|
|
99
|
-
|
91
|
+
The `@navBar` helper also takes options so if the above was instead instantiated with:
|
100
92
|
|
101
|
-
<%
|
102
|
-
|
93
|
+
<% @opts = nav_prefix:'<div>', nav_postfix: '</div>', link_prefix: '<span>', link_postfix: '</span>' %>
|
94
|
+
<%- @navBar @opts, (bar)=> %>
|
103
95
|
|
104
|
-
it would
|
96
|
+
it would generate
|
105
97
|
|
106
98
|
<div>
|
107
99
|
<span><a href="/foo">Bar</a></span>
|
108
100
|
<span><a href="http://ludicast.com">http://ludicast.com</a></span>
|
109
101
|
</div>
|
110
102
|
|
111
|
-
Also, if you want to make a site-
|
103
|
+
Also, if you want to make a site-wide change to the default NavBar settings, all you need to do is add these options to the NavBarConfig class (in Ruby) like
|
112
104
|
|
113
|
-
|
114
|
-
|
115
|
-
|
105
|
+
NavBarConfig[:nav_prefix] = "<div>"
|
106
|
+
NavBarConfig[:nav_postfix] = "</div>"
|
107
|
+
NavBarConfig[:link_prefix] = "<span>"
|
108
|
+
NavBarConfig[:link_postfix] = "</span>"
|
116
109
|
|
117
|
-
Then all links will generate with these options, unless overridden in the
|
118
|
-
|
119
|
-
bar.separator = "---"
|
120
|
-
bar.link_wrapper = function (link) {
|
121
|
-
if (link.match(/aa/)) {
|
122
|
-
return ""
|
123
|
-
} else {
|
124
|
-
return link
|
125
|
-
}
|
126
|
-
}
|
127
|
-
|
128
|
-
would cause
|
129
|
-
|
130
|
-
bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.link_to("gg") + bar.close()
|
131
|
-
|
132
|
-
to render as:
|
133
|
-
|
134
|
-
links.should.eql "<div><a href=\"ff\">ff</a>----<a href=\"gg\">gg</a></div>"
|
110
|
+
Then all links will generate with these options, unless overridden in the values passed it to `@navBar`.
|
135
111
|
|
136
112
|
## Routes
|
137
113
|
|
138
|
-
|
139
|
-
|
140
|
-
<% var nav = new NavBar() %>
|
141
|
-
<%= nav.open() %>
|
142
|
-
<%= nav.link_to("List Pizzas", pizzas_path() ) %>
|
143
|
-
<%= nav.link_to("Modify Pizza", edit_pizza_path({id: pizza.id})) %>
|
144
|
-
<%= nav.close() %>
|
114
|
+
Assuming that all your cubes are models that you are exposing to your app, we add to your eco templates routing helpers for every class inheriting from BaseCube. Therefore, if you have a cube class named `NoteDrop`, you will have the following helper methods available:
|
145
115
|
|
146
|
-
|
116
|
+
@newNotePath
|
117
|
+
@notesPath
|
118
|
+
@notePath(@note)
|
119
|
+
@editNotePath(@note)
|
147
120
|
|
148
|
-
|
149
|
-
<li><a href="/pizzas">List Pizzas</a></li>
|
150
|
-
<li><a href="/pizzas/2/edit">Modify Pizza</a></li>
|
151
|
-
</ul>
|
121
|
+
which are converted to the appropriate paths.
|
152
122
|
|
153
123
|
Note that some people might claim that it is insecure to expose your resources like this, but that probably should be dealt with on a case-by-case basis.
|
154
124
|
|
@@ -162,11 +132,13 @@ Note that some people might claim that it is insecure to expose your resources l
|
|
162
132
|
|
163
133
|
## Todo
|
164
134
|
|
135
|
+
* Allow Coffeescript (or Javascript) helpers to be read from an additional file.
|
165
136
|
* Add in form builders (from clots project)
|
166
|
-
*
|
167
|
-
*
|
168
|
-
*
|
137
|
+
* Haml support
|
138
|
+
* Use [Moneta](http://github.com/wycats/moneta) for caching autogenerated javascript files.
|
139
|
+
* Allowing Ice to render Rails partials
|
140
|
+
* Allowing Ice to serve as Rails layout files.
|
169
141
|
|
170
142
|
## Copyright
|
171
143
|
|
172
|
-
|
144
|
+
MIT Licence. See MIT-LICENSE file for details.
|
data/Rakefile
CHANGED
@@ -1,47 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
|
4
3
|
begin
|
5
|
-
require '
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "ice"
|
8
|
-
gem.summary = "User templates written in javascript"
|
9
|
-
gem.description = "User templates written in javascript"
|
10
|
-
gem.email = "nate@ludicast.com"
|
11
|
-
gem.homepage = "http://github.com/ludicast/ice"
|
12
|
-
gem.authors = ["Nate Kidwell"]
|
13
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
-
gem.add_dependency "therubyracer", "0.7.5"
|
15
|
-
gem.add_dependency "rails", "3.0.0"
|
16
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
-
end
|
18
|
-
Jeweler::GemcutterTasks.new
|
4
|
+
require 'bundler/setup'
|
19
5
|
rescue LoadError
|
20
|
-
puts
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
21
7
|
end
|
22
8
|
|
23
|
-
require '
|
24
|
-
|
25
|
-
spec.libs << 'lib' << 'spec'
|
26
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
-
end
|
9
|
+
require 'rake'
|
10
|
+
require 'rake/rdoctask'
|
28
11
|
|
29
|
-
|
30
|
-
|
31
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
-
spec.rcov = true
|
33
|
-
end
|
12
|
+
require 'rspec/core'
|
13
|
+
require 'rspec/core/rake_task'
|
34
14
|
|
35
|
-
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
36
16
|
|
37
17
|
task :default => :spec
|
38
18
|
|
39
|
-
|
40
|
-
Rake::RDocTask.new do |rdoc|
|
41
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
42
|
-
|
19
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
43
20
|
rdoc.rdoc_dir = 'rdoc'
|
44
|
-
rdoc.title
|
45
|
-
rdoc.
|
21
|
+
rdoc.title = 'Ice'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README.rdoc')
|
46
24
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
47
25
|
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'jasmine'
|
29
|
+
load 'jasmine/tasks/jasmine.rake'
|
30
|
+
rescue LoadError
|
31
|
+
task :jasmine do
|
32
|
+
abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
|
33
|
+
end
|
34
|
+
end
|
data/lib/ice.rb
CHANGED
@@ -2,10 +2,14 @@ require 'ice'
|
|
2
2
|
require 'ice/cubeable'
|
3
3
|
require 'ice/cube_association'
|
4
4
|
require 'ice/base_cube'
|
5
|
-
require 'ice/base'
|
6
5
|
|
6
|
+
require 'ice/railtie'
|
7
|
+
require 'ice/cube_helpers'
|
7
8
|
require 'rails'
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
require 'ice/eco_template/handler'
|
11
|
+
|
12
|
+
NavBarConfig = {}
|
13
|
+
|
14
|
+
|
15
|
+
ActionView::Template.register_template_handler :eco, Ice::EcoTemplate::Handler
|
data/lib/ice/base_cube.rb
CHANGED
@@ -2,9 +2,13 @@ module Ice
|
|
2
2
|
class BaseCube
|
3
3
|
extend Ice::CubeAssociation
|
4
4
|
|
5
|
-
def self.revealing(* attributes)
|
6
|
-
|
5
|
+
def self.revealing(* attributes)
|
6
|
+
unless @attribute_names
|
7
|
+
@attribute_names = []
|
8
|
+
end
|
9
|
+
@attribute_names.concat(attributes)
|
7
10
|
|
11
|
+
attributes.each do |attr|
|
8
12
|
define_method attr.to_sym do
|
9
13
|
@source.send(attr).to_ice
|
10
14
|
end
|
@@ -17,8 +21,34 @@ module Ice
|
|
17
21
|
self
|
18
22
|
end
|
19
23
|
|
24
|
+
def to_hash
|
25
|
+
if @attribute_names
|
26
|
+
hash = {:id => @source.id}
|
27
|
+
@attribute_names && @attribute_names.each do |name|
|
28
|
+
hash[name] = @source.send(name)
|
29
|
+
end
|
30
|
+
hash
|
31
|
+
else
|
32
|
+
@hash = @source.serializable_hash
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def id
|
37
|
+
@source.id
|
38
|
+
end
|
39
|
+
|
20
40
|
def initialize(source)
|
21
41
|
@source = source
|
42
|
+
unless @attribute_names
|
43
|
+
to_hash.each_key do |key|
|
44
|
+
unless self.respond_to? key.to_sym
|
45
|
+
self.class.send :define_method, key.to_sym do
|
46
|
+
@source.send(key.to_sym)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
22
51
|
end
|
52
|
+
|
23
53
|
end
|
24
54
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Object
|
2
|
+
def to_ice
|
3
|
+
nil
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
[FalseClass, TrueClass, Numeric, String].each do |cls|
|
8
|
+
cls.class_eval do
|
9
|
+
def to_ice
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Array
|
16
|
+
def to_ice
|
17
|
+
map &:to_ice
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Hash
|
22
|
+
def to_ice
|
23
|
+
res = {}
|
24
|
+
each_pair do |key,value|
|
25
|
+
res[key] = value.to_ice
|
26
|
+
end
|
27
|
+
res
|
28
|
+
end
|
29
|
+
end
|
data/lib/ice/cubeable.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
module Ice
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
2
|
+
module Cubeable
|
3
|
+
def get_cube_class(class_obj)
|
4
|
+
begin
|
5
|
+
cube_string = class_obj.to_s + "Cube"
|
6
|
+
cube_string.constantize
|
7
|
+
rescue
|
8
|
+
get_cube_class class_obj.superclass
|
10
9
|
end
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def to_ice
|
13
|
+
cube_class = get_cube_class self.class
|
14
|
+
cube_class.new self
|
16
15
|
end
|
16
|
+
end
|
17
17
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "ice/eco_template/context"
|
2
|
+
require 'eco'
|
3
|
+
require 'v8'
|
4
|
+
|
5
|
+
module Ice
|
6
|
+
module EcoTemplate
|
7
|
+
def self.convert_template(template_text, vars = {})
|
8
|
+
env = Context.new vars
|
9
|
+
context = V8::Context.new
|
10
|
+
context.eval(Eco::Source.combined_contents)
|
11
|
+
|
12
|
+
template = context["eco"]["compile"].call(template_text)
|
13
|
+
# Render the template
|
14
|
+
template.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|