stencils 0.0.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.
- data/Manifest +7 -0
- data/README +14 -0
- data/Rakefile +15 -0
- data/lib/stencils.rb +8 -0
- data/lib/stencils/stencil.rb +59 -0
- data/lib/stencils/stencil_context.rb +331 -0
- data/stencils.gemspec +30 -0
- data/stencils.tmproj +39 -0
- metadata +70 -0
data/Manifest
ADDED
data/README
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
= stencils
|
2
|
+
|
3
|
+
Rails gem that provides a way to reuse 'stencils' for common actions and views.
|
4
|
+
Stencils lets you define an action and views once and reuse them for different models.
|
5
|
+
A Stencil might typically be used for generic CRUD operations.
|
6
|
+
|
7
|
+
== Install
|
8
|
+
|
9
|
+
gem install stencils
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
...coming soon
|
14
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('stencils', '0.0.0') do |p|
|
6
|
+
p.description = "Lets you define an action and views once and reuse them for different models."
|
7
|
+
p.project = 'stencils'
|
8
|
+
p.url = "http://rubyforge.org/projects/stencils"
|
9
|
+
p.author = "Ryan Owens"
|
10
|
+
p.email = "ryan@infoether.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "stencils_notes.txt"]
|
12
|
+
p.development_dependencies = []
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/lib/stencils.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Stencils
|
2
|
+
|
3
|
+
module Stencil
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def stencil(name, options={})
|
12
|
+
@stencil_name = name
|
13
|
+
@stencil_options = options
|
14
|
+
@stencil_options[:name] = name
|
15
|
+
@stencil_options[:view_dir] ||= "stencils/#{name}"
|
16
|
+
|
17
|
+
#define a method here like setup_rest_stencil for the before filter.
|
18
|
+
#make the include and attr_accessor conditional so it only happens once.
|
19
|
+
#do whatever else is necessary to alow multiple stencils. (use instance_var_set with :@rest_stencil_options)
|
20
|
+
|
21
|
+
include RestStencil
|
22
|
+
attr_accessor :stencil
|
23
|
+
helper_method :stencil
|
24
|
+
before_filter :stencil_filter
|
25
|
+
helper "#{name.to_s.camelize}StencilHelper".constantize
|
26
|
+
end
|
27
|
+
|
28
|
+
def stencil_options
|
29
|
+
@stencil_options
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def stencil_filter
|
35
|
+
setup_stencil(self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup_stencil(model_or_class_or_symbol)
|
39
|
+
@stencil ||= StencilContext.new(self.response.template, model_or_class_or_symbol, self.class.stencil_options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_stencil(action=nil, options={})
|
43
|
+
action, options = nil, action if action.is_a? Hash
|
44
|
+
action ||= params[:action]
|
45
|
+
render(:template => stencil_template(action)) unless custom_stencil_template_exists?(action)
|
46
|
+
end
|
47
|
+
|
48
|
+
def stencil_template(action)
|
49
|
+
"stencils/#{stencil.stencil_name}/#{action}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def custom_stencil_template_exists?(action=params[:action])
|
53
|
+
custom_template_path = File.join(RAILS_ROOT, 'app', 'views', "#{stencil.collection_name}", action.to_s)
|
54
|
+
File.exist?("#{custom_template_path}.html.erb") || File.exist?("#{custom_template_path}.erb")
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,331 @@
|
|
1
|
+
module Stencils
|
2
|
+
|
3
|
+
class StencilContext
|
4
|
+
|
5
|
+
attr_accessor :template
|
6
|
+
attr_accessor :base_name
|
7
|
+
attr_accessor :stencil_name, :stencil_view_dir
|
8
|
+
|
9
|
+
def initialize(template, model_or_class_or_symbol, options={})
|
10
|
+
@template = template
|
11
|
+
@base_name = base_name_for(model_or_class_or_symbol)
|
12
|
+
@stencil_name = options.delete :name
|
13
|
+
@stencil_view_dir = options.delete :view_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
def base_name_for(model_or_class_or_symbol)
|
17
|
+
full_base_name = if model_or_class_or_symbol.kind_of? Class
|
18
|
+
model_or_class_or_symbol.name
|
19
|
+
elsif model_or_class_or_symbol.kind_of? Symbol
|
20
|
+
model_or_class_or_symbol.to_s.camelize
|
21
|
+
# elsif model_or_class_or_symbol.respond_to?(:controller)
|
22
|
+
elsif model_or_class_or_symbol.respond_to?(:controller)
|
23
|
+
model_or_class_or_symbol.controller.class.name
|
24
|
+
else
|
25
|
+
model_or_class_or_symbol.class.name
|
26
|
+
end
|
27
|
+
name = full_base_name.chomp('Test').chomp('Controller')
|
28
|
+
index = name.rindex(':')
|
29
|
+
index = index ? index+1 : 0
|
30
|
+
name[index,name.size]
|
31
|
+
end
|
32
|
+
|
33
|
+
def collection_class_name
|
34
|
+
#this singularize/pluralize chain lets you provide eg people/person and get people back, as opposed to peoples.
|
35
|
+
base_name.singularize.pluralize
|
36
|
+
end
|
37
|
+
|
38
|
+
def collection_name_base
|
39
|
+
collection_class_name.underscore.downcase
|
40
|
+
end
|
41
|
+
|
42
|
+
def collection_name
|
43
|
+
name = collection_name_base
|
44
|
+
name = "#{name}_collection" if uncountable? name
|
45
|
+
name
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_label
|
49
|
+
collection_name.titleize
|
50
|
+
end
|
51
|
+
|
52
|
+
def collection_symbol
|
53
|
+
collection_name.intern
|
54
|
+
end
|
55
|
+
|
56
|
+
def partial(name)
|
57
|
+
"#{collection_name}/#{name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def collection_partial
|
61
|
+
partial 'list_item'
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_collection_partial(model)
|
65
|
+
template.render :partial => collection_partial, :locals => {model_symbol => model}
|
66
|
+
end
|
67
|
+
|
68
|
+
def render_collection
|
69
|
+
html = []
|
70
|
+
collection.each do |model|
|
71
|
+
html << render_collection_partial(model)
|
72
|
+
end
|
73
|
+
html.join
|
74
|
+
end
|
75
|
+
|
76
|
+
def model_partial
|
77
|
+
# partial model_name
|
78
|
+
partial 'model'
|
79
|
+
end
|
80
|
+
|
81
|
+
def render_model
|
82
|
+
template.render :partial => model_partial, :locals => {model_symbol => model}
|
83
|
+
end
|
84
|
+
|
85
|
+
def form_partial
|
86
|
+
partial 'form'
|
87
|
+
end
|
88
|
+
|
89
|
+
def render_form(form)
|
90
|
+
template.render :partial => form_partial, :locals => {:form => form, model_symbol => model}
|
91
|
+
end
|
92
|
+
|
93
|
+
def model_class_name
|
94
|
+
collection_class_name.singularize
|
95
|
+
end
|
96
|
+
|
97
|
+
def model_name
|
98
|
+
model_class_name.underscore.downcase
|
99
|
+
end
|
100
|
+
|
101
|
+
def model_label
|
102
|
+
model_class_name.titleize
|
103
|
+
end
|
104
|
+
|
105
|
+
def new_or_old_label(new_label, old_label)
|
106
|
+
new_record? ? new_label : old_label
|
107
|
+
end
|
108
|
+
|
109
|
+
def new_or_edit_label(new_label="Add New #{model_label}", edit_label="Edit #{model_label}")
|
110
|
+
new_or_old_label new_label, edit_label
|
111
|
+
end
|
112
|
+
|
113
|
+
def model_instance_variable_name
|
114
|
+
"@#{model_name}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def collection_instance_variable_name
|
118
|
+
"@#{collection_name}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def collection_route
|
122
|
+
route = collection_name_base
|
123
|
+
route = "#{route}_index" if uncountable? route
|
124
|
+
route
|
125
|
+
end
|
126
|
+
|
127
|
+
def collection_url(options=nil)
|
128
|
+
args = adjust_hash_arg_to_last options
|
129
|
+
args.pop if args.last && args.last.empty?
|
130
|
+
args.delete_if {|arg| arg == nil || arg.kind_of?(ActiveRecord::Base)}
|
131
|
+
template.send "#{collection_route}_url", *args
|
132
|
+
end
|
133
|
+
|
134
|
+
def collection_path(options=nil)
|
135
|
+
args = adjust_hash_arg_to_last options
|
136
|
+
args.pop if args.last && args.last.empty?
|
137
|
+
args.delete_if {|arg| arg == nil || arg.kind_of?(ActiveRecord::Base)}
|
138
|
+
template.send "#{collection_route}_path", *args
|
139
|
+
end
|
140
|
+
|
141
|
+
def link_to_collection(options=nil)
|
142
|
+
template.link_to(collection_label, collection_path(options))
|
143
|
+
end
|
144
|
+
|
145
|
+
def show_route
|
146
|
+
"#{get_path_prefix}#{model_name}"
|
147
|
+
end
|
148
|
+
|
149
|
+
def show_path(model=self.model, options=nil)
|
150
|
+
|
151
|
+
args = adjust_hash_arg_to_last model, options
|
152
|
+
args.pop if args.last && args.last.empty?
|
153
|
+
args.delete_if {|arg| arg == nil}
|
154
|
+
|
155
|
+
puts "***show_path: "
|
156
|
+
puts "***model: #{model.inspect}"
|
157
|
+
puts "***args: #{args.inspect}"
|
158
|
+
|
159
|
+
template.send "#{show_route}_path", *args
|
160
|
+
end
|
161
|
+
|
162
|
+
def show_url(model=self.model, options=nil)
|
163
|
+
args = adjust_hash_arg_to_last model, options
|
164
|
+
args.pop if args.last && args.last.empty?
|
165
|
+
args.delete_if {|arg| arg == nil}
|
166
|
+
template.send "#{show_route}_url", *args
|
167
|
+
end
|
168
|
+
|
169
|
+
def edit_route
|
170
|
+
"edit_#{get_path_prefix}#{model_name}"
|
171
|
+
end
|
172
|
+
|
173
|
+
def edit_path(model=self.model, options=nil)
|
174
|
+
args = adjust_hash_arg_to_last model, options
|
175
|
+
args.pop if args.last && args.last.empty?
|
176
|
+
args.delete_if {|arg| arg == nil}
|
177
|
+
template.send "#{edit_route}_path", *args
|
178
|
+
end
|
179
|
+
|
180
|
+
def edit_path_url(model=self.model, options=nil)
|
181
|
+
args = adjust_hash_arg_to_last model, options
|
182
|
+
args.pop if args.last && args.last.empty?
|
183
|
+
args.delete_if {|arg| arg == nil}
|
184
|
+
template.send "#{edit_route}_url", *args
|
185
|
+
end
|
186
|
+
|
187
|
+
def new_route
|
188
|
+
"new_#{get_path_prefix}#{model_name}"
|
189
|
+
end
|
190
|
+
|
191
|
+
def new_path(options=nil)
|
192
|
+
route = "#{new_route}_path"
|
193
|
+
if options.blank?
|
194
|
+
template.send route
|
195
|
+
else
|
196
|
+
template.send route, options
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def new_path_url(options=nil)
|
201
|
+
route = "#{new_route}_url"
|
202
|
+
if options.blank?
|
203
|
+
template.send route
|
204
|
+
else
|
205
|
+
template.send route, options
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def get_path_prefix
|
210
|
+
path_prefix ? "#{path_prefix}_" : nil
|
211
|
+
end
|
212
|
+
|
213
|
+
def path_prefix
|
214
|
+
nil
|
215
|
+
end
|
216
|
+
|
217
|
+
def collection
|
218
|
+
instance_variable_get collection_instance_variable_name
|
219
|
+
end
|
220
|
+
|
221
|
+
def collection=(collection)
|
222
|
+
instance_variable_set collection_instance_variable_name, collection
|
223
|
+
end
|
224
|
+
alias_method :set_collection, :collection=
|
225
|
+
|
226
|
+
def model
|
227
|
+
instance_variable_get model_instance_variable_name
|
228
|
+
end
|
229
|
+
|
230
|
+
def model=(model)
|
231
|
+
puts "***model= : #{model_instance_variable_name}"
|
232
|
+
instance_variable_set model_instance_variable_name, model
|
233
|
+
end
|
234
|
+
alias_method :set_model, :model=
|
235
|
+
|
236
|
+
def model_class
|
237
|
+
Kernel.const_get(model_class_name)
|
238
|
+
end
|
239
|
+
|
240
|
+
def fixture_model(name=nil)
|
241
|
+
template.send collection_name_base, name
|
242
|
+
end
|
243
|
+
|
244
|
+
def model_symbol
|
245
|
+
model_name.intern
|
246
|
+
end
|
247
|
+
|
248
|
+
def adjust_hash_arg_to_last(*args)
|
249
|
+
hash_arg = nil
|
250
|
+
args.each_with_index do |arg,index|
|
251
|
+
if arg.kind_of? Hash
|
252
|
+
hash_arg = arg
|
253
|
+
end
|
254
|
+
if hash_arg
|
255
|
+
if index == args.size-1
|
256
|
+
args[index] = hash_arg
|
257
|
+
else
|
258
|
+
args[index] = nil
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
args
|
263
|
+
end
|
264
|
+
|
265
|
+
##UTILS MOVED THESE OUT OF RestControllerExtension so they could be used separately
|
266
|
+
|
267
|
+
def find_model_with_param_id
|
268
|
+
model_id = "#{model_name}_id"
|
269
|
+
param = params[model_id] || params[:id]
|
270
|
+
self.set_model model_class.find(param)
|
271
|
+
end
|
272
|
+
|
273
|
+
def new_model
|
274
|
+
self.set_model model_class.new
|
275
|
+
end
|
276
|
+
|
277
|
+
def new_model_with_params
|
278
|
+
self.set_model model_class.new(model_params)
|
279
|
+
end
|
280
|
+
|
281
|
+
def create_model_with_params
|
282
|
+
self.set_model model_class.create(model_params)
|
283
|
+
end
|
284
|
+
|
285
|
+
def update_model_with_params
|
286
|
+
find_model_with_param_id
|
287
|
+
self.model.update_attributes(model_params)
|
288
|
+
end
|
289
|
+
|
290
|
+
def init_model_with_params
|
291
|
+
find_model_with_param_id
|
292
|
+
self.model.attributes = model_params
|
293
|
+
end
|
294
|
+
|
295
|
+
def destroy_model_with_param_id
|
296
|
+
find_model_with_param_id.destroy
|
297
|
+
end
|
298
|
+
|
299
|
+
def save_model
|
300
|
+
self.model.save
|
301
|
+
end
|
302
|
+
|
303
|
+
def new_record?
|
304
|
+
model.new_record?
|
305
|
+
end
|
306
|
+
|
307
|
+
def model_params
|
308
|
+
params[model_symbol]
|
309
|
+
end
|
310
|
+
|
311
|
+
def params
|
312
|
+
template.params
|
313
|
+
end
|
314
|
+
|
315
|
+
def instance_variable_set(name, value)
|
316
|
+
super
|
317
|
+
template.instance_variable_set name, value
|
318
|
+
template.controller.instance_variable_set name, value
|
319
|
+
end
|
320
|
+
|
321
|
+
def instance_variable_get(name)
|
322
|
+
super || template.instance_variable_get(name) || template.controller.instance_variable_get(name)
|
323
|
+
end
|
324
|
+
|
325
|
+
def uncountable?(name)
|
326
|
+
ActiveSupport::Inflector.inflections.uncountables.include? name
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
data/stencils.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{stencils}
|
5
|
+
s.version = "0.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Ryan Owens"]
|
9
|
+
s.date = %q{2009-07-24}
|
10
|
+
s.description = %q{Lets you define an action and views once and reuse them for different models.}
|
11
|
+
s.email = %q{ryan@infoether.com}
|
12
|
+
s.extra_rdoc_files = ["lib/stencils/stencil.rb", "lib/stencils/stencil_context.rb", "lib/stencils.rb", "README"]
|
13
|
+
s.files = ["lib/stencils/stencil.rb", "lib/stencils/stencil_context.rb", "lib/stencils.rb", "Rakefile", "README", "stencils.tmproj", "Manifest", "stencils.gemspec"]
|
14
|
+
s.homepage = %q{http://rubyforge.org/projects/stencils}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Stencils", "--main", "README"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{stencils}
|
18
|
+
s.rubygems_version = %q{1.3.3}
|
19
|
+
s.summary = %q{Lets you define an action and views once and reuse them for different models.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
data/stencils.tmproj
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>documents</key>
|
6
|
+
<array>
|
7
|
+
<dict>
|
8
|
+
<key>expanded</key>
|
9
|
+
<true/>
|
10
|
+
<key>name</key>
|
11
|
+
<string>stencils</string>
|
12
|
+
<key>regexFolderFilter</key>
|
13
|
+
<string>!.*/(\coverage|\.svn|\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
|
14
|
+
<key>sourceDirectory</key>
|
15
|
+
<string></string>
|
16
|
+
</dict>
|
17
|
+
</array>
|
18
|
+
<key>fileHierarchyDrawerWidth</key>
|
19
|
+
<integer>370</integer>
|
20
|
+
<key>metaData</key>
|
21
|
+
<dict/>
|
22
|
+
<key>showFileHierarchyDrawer</key>
|
23
|
+
<false/>
|
24
|
+
<key>showFileHierarchyPanel</key>
|
25
|
+
<true/>
|
26
|
+
<key>treeState</key>
|
27
|
+
<dict>
|
28
|
+
<key>stencils</key>
|
29
|
+
<dict>
|
30
|
+
<key>isExpanded</key>
|
31
|
+
<true/>
|
32
|
+
<key>subItems</key>
|
33
|
+
<dict/>
|
34
|
+
</dict>
|
35
|
+
</dict>
|
36
|
+
<key>windowFrame</key>
|
37
|
+
<string>{{0, 64}, {1680, 964}}</string>
|
38
|
+
</dict>
|
39
|
+
</plist>
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stencils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Owens
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-24 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Lets you define an action and views once and reuse them for different models.
|
17
|
+
email: ryan@infoether.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/stencils/stencil.rb
|
24
|
+
- lib/stencils/stencil_context.rb
|
25
|
+
- lib/stencils.rb
|
26
|
+
- README
|
27
|
+
files:
|
28
|
+
- lib/stencils/stencil.rb
|
29
|
+
- lib/stencils/stencil_context.rb
|
30
|
+
- lib/stencils.rb
|
31
|
+
- Rakefile
|
32
|
+
- README
|
33
|
+
- stencils.tmproj
|
34
|
+
- Manifest
|
35
|
+
- stencils.gemspec
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://rubyforge.org/projects/stencils
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options:
|
42
|
+
- --line-numbers
|
43
|
+
- --inline-source
|
44
|
+
- --title
|
45
|
+
- Stencils
|
46
|
+
- --main
|
47
|
+
- README
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "1.2"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: stencils
|
65
|
+
rubygems_version: 1.3.3
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: Lets you define an action and views once and reuse them for different models.
|
69
|
+
test_files: []
|
70
|
+
|