el 0.5.0
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 +15 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/LICENSE +19 -0
- data/README.md +77 -0
- data/Rakefile +47 -0
- data/docs/Assets.md +157 -0
- data/docs/CRUD.md +255 -0
- data/docs/CacheManager.md +66 -0
- data/docs/ContentHelpers.md +64 -0
- data/docs/TagFactory.md +201 -0
- data/el.gemspec +23 -0
- data/lib/el.rb +11 -0
- data/lib/el/assets.rb +126 -0
- data/lib/el/cache.rb +96 -0
- data/lib/el/constants.rb +21 -0
- data/lib/el/content_helpers.rb +61 -0
- data/lib/el/crud.rb +239 -0
- data/lib/el/ipcm.rb +67 -0
- data/lib/el/tag_factory.rb +180 -0
- data/lib/el/utils.rb +37 -0
- data/test/assets/master.css +1 -0
- data/test/assets/master.js +1 -0
- data/test/assets/master.png +0 -0
- data/test/helpers.rb +14 -0
- data/test/ipcm/config.ru +25 -0
- data/test/ipcm/view/compiler_test.erb +1 -0
- data/test/setup.rb +11 -0
- data/test/sprockets/app.css +5 -0
- data/test/sprockets/app.js +7 -0
- data/test/sprockets/ui.css +3 -0
- data/test/sprockets/ui.js +5 -0
- data/test/test__assets.rb +276 -0
- data/test/test__cache.rb +145 -0
- data/test/test__content_helpers.rb +41 -0
- data/test/test__crud.rb +269 -0
- data/test/test__ipcm.rb +127 -0
- data/test/test__sprockets.rb +101 -0
- data/test/test__tag_factory.rb +170 -0
- metadata +124 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
## Cache Manager
|
3
|
+
|
4
|
+
Allows to cache the result of an arbitrary block and use the result on consequent requests.
|
5
|
+
|
6
|
+
*Note: Value is not stored if block returns false or nil.*
|
7
|
+
|
8
|
+
Cache can be cleared by calling `clear_cache!` method.
|
9
|
+
|
10
|
+
If called without params, all cache will be cleared.
|
11
|
+
|
12
|
+
To clear only specific blocks, pass their IDs as params.
|
13
|
+
|
14
|
+
**Example:**
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
class App < E
|
18
|
+
|
19
|
+
def index
|
20
|
+
@db_items = cache :db_items do
|
21
|
+
# fetching items
|
22
|
+
end
|
23
|
+
@banners = cache :banners do
|
24
|
+
# render banners partial
|
25
|
+
end
|
26
|
+
# ...
|
27
|
+
end
|
28
|
+
|
29
|
+
def products
|
30
|
+
cache do
|
31
|
+
# fetch and render products
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
if 'some condition occurred'
|
37
|
+
# clearing cache only for @banners and @db_items
|
38
|
+
clear_cache! :banners, :db_items
|
39
|
+
end
|
40
|
+
if 'some another condition occurred'
|
41
|
+
# clearing all cache
|
42
|
+
clear_cache!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
By default, the cache will be kept in memory.<br>
|
50
|
+
If you want to use a different pool, set it by using `cache_pool` at app level.
|
51
|
+
|
52
|
+
Just make sure your pool behaves like a Hash,
|
53
|
+
Meant it should respond to `[]=`, `[]`, `delete` and `clear`.
|
54
|
+
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# controllers...
|
58
|
+
|
59
|
+
app = E.new do
|
60
|
+
cache_pool SomePool
|
61
|
+
mount Something
|
62
|
+
end
|
63
|
+
app.run
|
64
|
+
```
|
65
|
+
|
66
|
+
**[ [contents ↑](https://github.com/espresso/espresso-lungo#use) ]**
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
## content_for
|
3
|
+
|
4
|
+
Allow to capture content and then render it into a different place:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
content_for :assets do
|
8
|
+
js_tag :jquery
|
9
|
+
end
|
10
|
+
|
11
|
+
# later in views
|
12
|
+
yield_content :assets
|
13
|
+
#=> '<script src="jquery.js" type="text/javascript"></script>'
|
14
|
+
```
|
15
|
+
|
16
|
+
Use `content_for?` to check whether content block exists for some key:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
p content_for?(:assets)
|
20
|
+
#=> #<Proc:0x00...
|
21
|
+
|
22
|
+
p content_for?(:blah)
|
23
|
+
#=> nil
|
24
|
+
```
|
25
|
+
|
26
|
+
It is also possible to pass any variables into content block:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
content_for :account do |name, email|
|
30
|
+
form_tag! do
|
31
|
+
input_tag(value: name) +
|
32
|
+
input_tag(value: email)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# somewhere in views
|
37
|
+
yield_content :account, :foo, 'foo@bar.com'
|
38
|
+
#=> '<form><input value="foo"><input value="foo@bar.com"></form>'
|
39
|
+
```
|
40
|
+
|
41
|
+
Please note that content block will be executed every time you call `yield_content`.
|
42
|
+
|
43
|
+
If you are using same content block multiple times on same page please consider to assign the result to a variable and use it repeatedly to avoid performance decreasing.
|
44
|
+
|
45
|
+
**[ [contents ↑](https://github.com/espresso/espresso-lungo#use) ]**
|
46
|
+
|
47
|
+
## capture_html
|
48
|
+
|
49
|
+
Execute given content block and return the result.
|
50
|
+
|
51
|
+
Useful when you need to display same snippet multiple times and want it rendered only once.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
html = capture_html do
|
55
|
+
js_tag(:jquery) +
|
56
|
+
css_tag(:ui)
|
57
|
+
end
|
58
|
+
|
59
|
+
puts html
|
60
|
+
#=> <script src="jquery.js" type="text/javascript"></script>
|
61
|
+
#=> <link href="ui.css" media="all" type="text/css" rel="stylesheet">
|
62
|
+
```
|
63
|
+
|
64
|
+
**[ [contents ↑](https://github.com/espresso/espresso-lungo#use) ]**
|
data/docs/TagFactory.md
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
|
2
|
+
## Generic Tags
|
3
|
+
|
4
|
+
`Espresso Lungo` comes with a set of useful helpers aimed at generating HTML in plain Ruby:
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
div_tag 'some text'
|
8
|
+
#=> <div>some text</div>
|
9
|
+
```
|
10
|
+
|
11
|
+
HTML attributes can be passed via options Hash:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
h1_tag 'Welcome!', class: 'well'
|
15
|
+
#=> <h1 class="well">Welcome!</h1>
|
16
|
+
```
|
17
|
+
|
18
|
+
Content can be provided via block:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
script_tag do
|
22
|
+
// some js here
|
23
|
+
end
|
24
|
+
#=> <script>
|
25
|
+
#=> // some js here
|
26
|
+
#=> </script>
|
27
|
+
```
|
28
|
+
|
29
|
+
**Important!** Any content, provided via first argument or block, will be HTML escaped!
|
30
|
+
To emit content as is, use bang methods and MAKE SURE you do not pass any untrusted input into HTML helpers!
|
31
|
+
|
32
|
+
**Default Behavior:**
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
div_tag 'some <evil> string'
|
36
|
+
#=> <div>some <evil> string</div>
|
37
|
+
```
|
38
|
+
|
39
|
+
**Bang helpers wont escape output! Use with care!**
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
div_tag! 'some <evil> string'
|
43
|
+
#=> <div>some <evil> string</div>
|
44
|
+
```
|
45
|
+
|
46
|
+
Though bang methods are mostly dangerous, they are necessary when using nested tags:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
div_tag! do # without bang <b> tag will be escaped
|
50
|
+
b_tag 'some <evil> string'
|
51
|
+
end
|
52
|
+
#=> <div><b>some <evil> string</b></div>
|
53
|
+
```
|
54
|
+
|
55
|
+
The main concern when using nested tags is to not mix helpers with any untrusted input.
|
56
|
+
|
57
|
+
**Note:** when using multiple tags you have to concat them, otherwise only the last one will be shown:
|
58
|
+
|
59
|
+
**Wrong:**
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
form_tag! do
|
63
|
+
input_tag(name: :name)
|
64
|
+
input_tag(name: :email)
|
65
|
+
end
|
66
|
+
#=> <form><input name="email"></form>
|
67
|
+
```
|
68
|
+
|
69
|
+
**Correct:**
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
form_tag! do
|
73
|
+
input_tag(name: :name) + # or <<
|
74
|
+
input_tag(name: :email)
|
75
|
+
end
|
76
|
+
#=> <form><input name="name"><input name="email"></form>
|
77
|
+
```
|
78
|
+
|
79
|
+
**[ [contents ↑](https://github.com/espresso/espresso-lungo#use) ]**
|
80
|
+
|
81
|
+
|
82
|
+
## link_to
|
83
|
+
|
84
|
+
`link_to` allow to build a HTML <a> tag.
|
85
|
+
|
86
|
+
If first param is a valid action, the URL of given action will be used.
|
87
|
+
|
88
|
+
Action accepted as a symbol or a string representing action name and format.
|
89
|
+
|
90
|
+
Action can also be passed in deRESTified form, eg. `:read` instead of `:post_read`
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class App < E
|
94
|
+
format '.html'
|
95
|
+
|
96
|
+
def read
|
97
|
+
link_to :read #=> <a href="/app/read" ...
|
98
|
+
link_to 'read.html' #=> <a href="/app/read.html" ...
|
99
|
+
link_to 'read.xml' #=> <a href="read.xml" ... - not translated, used as is
|
100
|
+
end
|
101
|
+
|
102
|
+
def post_write
|
103
|
+
link_to :post_write #=> <a href="/app/write" ... - works but it is tedious, use :write instead
|
104
|
+
link_to :write #=> <a href="/app/write" ...
|
105
|
+
link_to 'write.html' #=> <a href="/app/write.html" ...
|
106
|
+
link_to '/something' #=> <a href="/something" ... - not translated, used as is
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
When you need to create a link to an arbitrary controller, use `base_url`, `route` or `[]` of target controller:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
class News < E
|
115
|
+
format '.html'
|
116
|
+
|
117
|
+
def home
|
118
|
+
# ...
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_read id = nil
|
122
|
+
# ...
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
link_to News.base_url #=> <a href="/news" ...
|
128
|
+
link_to News[:home] #=> <a href="/news/home" ...
|
129
|
+
link_to News['home.html'] #=> <a href="/news/home.html" ...
|
130
|
+
link_to News[:get_read] #=> <a href="/news/read" ...
|
131
|
+
link_to News[:read] #=> <a href="/news/read" ...
|
132
|
+
link_to News['read.html'] #=> <a href="/news/read.html" ...
|
133
|
+
|
134
|
+
link_to News.route(:read, 100) #=> <a href="/news/read/100" ...
|
135
|
+
link_to News.route(:read, '100.html') #=> <a href="/news/read/100.html" ...
|
136
|
+
```
|
137
|
+
|
138
|
+
|
139
|
+
If `nil` passed as first argument, a void link will be created:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
link_to nil, 'something'
|
143
|
+
#=> <a href="javascript:void(null);>something</a>
|
144
|
+
```
|
145
|
+
|
146
|
+
Anchor can be passed via second argument.
|
147
|
+
|
148
|
+
If it is missing, the link will be used as anchor:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
link_to :something
|
152
|
+
#=> <a href="/something">/something</a>
|
153
|
+
|
154
|
+
link_to :foo, 'bar'
|
155
|
+
#=> <a href="/foo">bar</a>
|
156
|
+
```
|
157
|
+
|
158
|
+
Anchor can also be passed as a block:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
link_to(:foo) { 'bar' }
|
162
|
+
#=> <a href="/foo>bar</a>
|
163
|
+
```
|
164
|
+
|
165
|
+
|
166
|
+
**Important!** Anchor will be HTML escaped:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
link_to(:foo) { 'some <evil>' }
|
170
|
+
#=> <a href="/foo>some <evil></a>
|
171
|
+
```
|
172
|
+
|
173
|
+
To emit content as is, use bang method instead and make sure you do not pass any untrusted content to `link_to` helper:
|
174
|
+
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
link_to! :foo, 'some <evil>'
|
178
|
+
#=> <a href="/foo>some <evil></a>
|
179
|
+
```
|
180
|
+
|
181
|
+
Also you'll need bang helper when you build nested tags:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
link_to! :foo do
|
185
|
+
b_tag 'some text'
|
186
|
+
end
|
187
|
+
#=> <a href="/foo><b>some text</b></a>
|
188
|
+
```
|
189
|
+
|
190
|
+
|
191
|
+
Attributes can be passed as a hash via last argument:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
link_to :foo, target: '_blank'
|
195
|
+
#=> <a href="/foo" target="_blank">/foo</a>
|
196
|
+
|
197
|
+
link_to :foo, :bar, target: '_blank'
|
198
|
+
#=> <a href="/foo" target="_blank">bar</a>
|
199
|
+
```
|
200
|
+
|
201
|
+
**[ [contents ↑](https://github.com/espresso/espresso-lungo#use) ]**
|
data/el.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
version = '0.5.0'
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
|
6
|
+
s.name = 'el'
|
7
|
+
s.version = version
|
8
|
+
s.authors = ['Silviu Rusu']
|
9
|
+
s.email = ['slivuz@gmail.com']
|
10
|
+
s.homepage = 'https://github.com/espresso/espresso-lungo'
|
11
|
+
s.summary = 'el-%s' % version
|
12
|
+
s.description = 'Espresso Lungo - Extra Libs for Espresso Framework'
|
13
|
+
|
14
|
+
s.required_ruby_version = '>= 1.9.2'
|
15
|
+
s.add_dependency 'e', '>= 0.4.8'
|
16
|
+
s.add_dependency 'sprockets'
|
17
|
+
|
18
|
+
s.add_development_dependency 'bundler'
|
19
|
+
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
s.files = Dir['**/{*,.[a-z]*}'].reject {|e| e =~ /\.(gem|lock)\Z/}
|
22
|
+
s.licenses = ['MIT']
|
23
|
+
end
|
data/lib/el.rb
ADDED
data/lib/el/assets.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module EL
|
2
|
+
class AssetsMapper
|
3
|
+
include TagFactory
|
4
|
+
|
5
|
+
attr_reader :baseurl, :wd
|
6
|
+
|
7
|
+
# @example
|
8
|
+
#
|
9
|
+
# assets_mapper :vendor do
|
10
|
+
#
|
11
|
+
# js_tag :jquery
|
12
|
+
#
|
13
|
+
# chdir 'jquery-ui'
|
14
|
+
# js_tag 'js/jquery-ui.min'
|
15
|
+
# css_tag 'css/jquery-ui.min'
|
16
|
+
#
|
17
|
+
# cd '../bootstrap'
|
18
|
+
# js_tag 'js/bootstrap.min'
|
19
|
+
# css_tag 'css/bootstrap'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# #=> <script src="/vendor/jquery.js" ...
|
23
|
+
# #=> <script src="/vendor/jquery-ui/js/jquery-ui.min.js" ...
|
24
|
+
# #=> <link href="/vendor/jquery-ui/css/jquery-ui.min.css" ...
|
25
|
+
# #=> <script src="/vendor/bootstrap/js/bootstrap.min.js" ...
|
26
|
+
# #=> <link href="/vendor/bootstrap/css/bootstrap.css" ...
|
27
|
+
#
|
28
|
+
def initialize baseurl, opts = {}, &proc
|
29
|
+
@opts = Hash[opts]
|
30
|
+
@suffix = @opts.delete(:suffix) || ''
|
31
|
+
baseurl = baseurl.to_s.dup.strip
|
32
|
+
baseurl.empty? ? baseurl = nil : (baseurl =~ /\/\Z/ || baseurl << '/')
|
33
|
+
@baseurl, @wd = baseurl.freeze, nil
|
34
|
+
proc && self.instance_exec(&proc)
|
35
|
+
end
|
36
|
+
|
37
|
+
(%w[js css] + EConstants::IMAGE_TAGS).each do |tag|
|
38
|
+
define_method tag + '_tag' do |src, attrs={}|
|
39
|
+
super src, attrs.merge(suffix: @suffix)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def chdir path = nil
|
44
|
+
return @wd = nil unless path
|
45
|
+
wd = []
|
46
|
+
if (path = path.to_s) =~ /\A\//
|
47
|
+
path = path.sub(/\A\/+/, '')
|
48
|
+
path = path.empty? ? [] : [path]
|
49
|
+
else
|
50
|
+
dirs_back, path = path.split(/\/+/).partition { |c| c == '..' }
|
51
|
+
if @wd
|
52
|
+
wd_chunks = @wd.split(/\/+/)
|
53
|
+
wd = wd_chunks[0, wd_chunks.size - dirs_back.size] || []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@wd = (wd + path << '').compact.join('/').freeze
|
57
|
+
end
|
58
|
+
alias :cd :chdir
|
59
|
+
|
60
|
+
private
|
61
|
+
def assets_url path = nil
|
62
|
+
chunks = [baseurl, wd, path] # assigning array to a variable
|
63
|
+
chunks.select! {|c| c && c.size > 0} # and work on it
|
64
|
+
File.join(*chunks) # is 2x faster than array#select {...}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class E
|
71
|
+
include EL::TagFactory
|
72
|
+
|
73
|
+
def assets *args, &proc
|
74
|
+
app.assets *args, &proc
|
75
|
+
end
|
76
|
+
|
77
|
+
def assets_mapper *args, &proc
|
78
|
+
EL::AssetsMapper.new *args, &proc
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
def assets_url path = nil
|
83
|
+
path ?
|
84
|
+
(app.assets_url ? File.join(app.assets_url, path.to_s) : path.to_s) :
|
85
|
+
(app.assets_url ? app.assets_url : '')
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
class EBuilder
|
91
|
+
|
92
|
+
# set the baseurl for assets.
|
93
|
+
# by default, assets URL is empty.
|
94
|
+
#
|
95
|
+
# @example assets_url not set
|
96
|
+
# script_tag 'master.js'
|
97
|
+
# => <script src="master.js"
|
98
|
+
# style_tag 'theme.css'
|
99
|
+
# => <link href="theme.css"
|
100
|
+
#
|
101
|
+
# @example assets_url set to /assets
|
102
|
+
#
|
103
|
+
# script_tag 'master.js'
|
104
|
+
# => <script src="/assets/master.js"
|
105
|
+
# style_tag 'theme.css'
|
106
|
+
# => <link href="/assets/theme.css"
|
107
|
+
#
|
108
|
+
# @note
|
109
|
+
# by default, Sprockets will be used to serve static files.
|
110
|
+
# to disable this, set second argument to false.
|
111
|
+
#
|
112
|
+
def assets_url url = nil, server = true
|
113
|
+
return @assets_url if @assets_url
|
114
|
+
url = url.to_s.dup.strip
|
115
|
+
url = url =~ /\A[\w|\d]+\:\/\//i ? url : EUtils.rootify_url(url)
|
116
|
+
@assets_url = (url =~ /\/\Z/ ? url : String.new(url) << '/').freeze
|
117
|
+
return unless server
|
118
|
+
mount_application(assets, @assets_url, on: :GET)
|
119
|
+
end
|
120
|
+
alias assets_map assets_url
|
121
|
+
|
122
|
+
def assets
|
123
|
+
@sprockets_env ||= Sprockets::Environment.new(root)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|