rails 0.9.5 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rails might be problematic. Click here for more details.
- data/CHANGELOG +46 -0
- data/README +36 -8
- data/Rakefile +18 -25
- data/bin/console +17 -30
- data/bin/console_sandbox.rb +6 -0
- data/bin/destroy +5 -0
- data/bin/generate +2 -70
- data/bin/rails +4 -28
- data/bin/server +4 -2
- data/bin/update +5 -0
- data/configs/apache.conf +7 -54
- data/configs/empty.log +0 -0
- data/configs/routes.rb +15 -0
- data/environments/shared.rb +14 -6
- data/environments/shared_for_gem.rb +12 -6
- data/fresh_rakefile +40 -8
- data/html/index.html +70 -1
- data/lib/breakpoint.rb +6 -1
- data/lib/breakpoint_client.rb +196 -193
- data/lib/dispatcher.rb +16 -38
- data/lib/rails_generator.rb +39 -198
- data/lib/rails_generator/base.rb +203 -0
- data/lib/rails_generator/commands.rb +409 -0
- data/lib/rails_generator/generators/applications/app/USAGE +16 -0
- data/lib/rails_generator/generators/applications/app/app_generator.rb +120 -0
- data/lib/rails_generator/generators/components/controller/USAGE +30 -0
- data/lib/rails_generator/generators/components/controller/controller_generator.rb +37 -0
- data/{generators → lib/rails_generator/generators/components}/controller/templates/controller.rb +1 -1
- data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +18 -0
- data/{generators → lib/rails_generator/generators/components}/controller/templates/helper.rb +0 -0
- data/{generators → lib/rails_generator/generators/components}/controller/templates/view.rhtml +0 -0
- data/lib/rails_generator/generators/components/mailer/USAGE +19 -0
- data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +32 -0
- data/{generators → lib/rails_generator/generators/components}/mailer/templates/fixture.rhtml +0 -0
- data/{generators → lib/rails_generator/generators/components}/mailer/templates/mailer.rb +0 -0
- data/{generators → lib/rails_generator/generators/components}/mailer/templates/unit_test.rb +7 -1
- data/{generators → lib/rails_generator/generators/components}/mailer/templates/view.rhtml +0 -0
- data/lib/rails_generator/generators/components/model/USAGE +17 -0
- data/lib/rails_generator/generators/components/model/model_generator.rb +18 -0
- data/{generators/scaffold → lib/rails_generator/generators/components/model}/templates/fixtures.yml +0 -2
- data/{generators → lib/rails_generator/generators/components}/model/templates/model.rb +0 -0
- data/{generators → lib/rails_generator/generators/components}/model/templates/unit_test.rb +5 -1
- data/lib/rails_generator/generators/components/scaffold/USAGE +32 -0
- data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +178 -0
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/controller.rb +1 -1
- data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +5 -0
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/functional_test.rb +7 -6
- data/lib/rails_generator/generators/components/scaffold/templates/helper.rb +2 -0
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/layout.rhtml +1 -1
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/style.css +17 -17
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/view_edit.rhtml +1 -1
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/view_list.rhtml +1 -1
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/view_new.rhtml +1 -1
- data/{generators → lib/rails_generator/generators/components}/scaffold/templates/view_show.rhtml +0 -0
- data/lib/rails_generator/lookup.rb +200 -0
- data/lib/rails_generator/manifest.rb +53 -0
- data/lib/rails_generator/options.rb +134 -0
- data/lib/rails_generator/scripts.rb +83 -0
- data/lib/rails_generator/scripts/destroy.rb +7 -0
- data/lib/rails_generator/scripts/generate.rb +7 -0
- data/lib/rails_generator/scripts/update.rb +12 -0
- data/lib/rails_generator/simple_logger.rb +46 -0
- data/lib/rails_generator/spec.rb +44 -0
- data/lib/webrick_server.rb +15 -65
- metadata +92 -48
- data/doc/apache_protection +0 -3
- data/doc/index.html +0 -70
- data/generators/controller/USAGE +0 -28
- data/generators/controller/controller_generator.rb +0 -26
- data/generators/controller/templates/functional_test.rb +0 -17
- data/generators/mailer/USAGE +0 -27
- data/generators/mailer/mailer_generator.rb +0 -22
- data/generators/model/USAGE +0 -17
- data/generators/model/model_generator.rb +0 -10
- data/generators/model/templates/fixtures.yml +0 -1
- data/generators/scaffold/USAGE +0 -27
- data/generators/scaffold/scaffold_generator.rb +0 -60
@@ -0,0 +1,409 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'optparse'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
module Generator
|
8
|
+
module Commands
|
9
|
+
# Here's a convenient way to get a handle on generator commands.
|
10
|
+
# Command.instance('destroy', my_generator) instantiates a Destroy
|
11
|
+
# delegate of my_generator ready to do your dirty work.
|
12
|
+
def self.instance(command, generator)
|
13
|
+
const_get(command.to_s.camelize).new(generator)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Even more convenient access to commands. Include Commands in
|
17
|
+
# the generator Base class to get a nice #command instance method
|
18
|
+
# which returns a delegate for the requested command.
|
19
|
+
def self.append_features(base)
|
20
|
+
base.send(:define_method, :command) do |command|
|
21
|
+
Commands.instance(command, self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Generator commands delegate Rails::Generator::Base and implement
|
27
|
+
# a standard set of actions. Their behavior is defined by the way
|
28
|
+
# they respond to these actions: Create brings life; Destroy brings
|
29
|
+
# death; List passively observes.
|
30
|
+
#
|
31
|
+
# Commands are invoked by replaying (or rewinding) the generator's
|
32
|
+
# manifest of actions. See Rails::Generator::Manifest and
|
33
|
+
# Rails::Generator::Base#manifest method that generator subclasses
|
34
|
+
# are required to override.
|
35
|
+
#
|
36
|
+
# Commands allows generators to "plug in" invocation behavior, which
|
37
|
+
# corresponds to the GoF Strategy pattern.
|
38
|
+
class Base < DelegateClass(Rails::Generator::Base)
|
39
|
+
# Replay action manifest. RewindBase subclass rewinds manifest.
|
40
|
+
def invoke!
|
41
|
+
manifest.replay(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def dependency(generator_name, args, runtime_options = {})
|
45
|
+
logger.dependency(generator_name) do
|
46
|
+
self.class.new(instance(generator_name, args, full_options(runtime_options))).invoke!
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Does nothing for all commands except Create.
|
51
|
+
def class_collisions(*class_names)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Does nothing for all commands except Create.
|
55
|
+
def readme(*args)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
# Ask the user interactively whether to force collision.
|
60
|
+
def force_file_collision?(destination)
|
61
|
+
$stdout.print "overwrite #{destination}? [Ynaq] "
|
62
|
+
case $stdin.gets
|
63
|
+
when /a/i
|
64
|
+
$stdout.puts "forcing #{spec.name}"
|
65
|
+
options[:collision] = :force
|
66
|
+
when /q/i
|
67
|
+
$stdout.puts "aborting #{spec.name}"
|
68
|
+
raise SystemExit
|
69
|
+
when /n/i then :skip
|
70
|
+
else :force
|
71
|
+
end
|
72
|
+
rescue
|
73
|
+
retry
|
74
|
+
end
|
75
|
+
|
76
|
+
def render_template_part(template_options)
|
77
|
+
# Getting Sandbox to evaluate part template in it
|
78
|
+
part_binding = template_options[:sandbox].call.sandbox_binding
|
79
|
+
part_rel_path = template_options[:insert]
|
80
|
+
part_path = source_path(part_rel_path)
|
81
|
+
|
82
|
+
# Render inner template within Sandbox binding
|
83
|
+
rendered_part = ERB.new(File.readlines(part_path).join, nil, '-').result(part_binding)
|
84
|
+
begin_mark = template_part_mark(template_options[:begin_mark], template_options[:mark_id])
|
85
|
+
end_mark = template_part_mark(template_options[:end_mark], template_options[:mark_id])
|
86
|
+
begin_mark + rendered_part + end_mark
|
87
|
+
end
|
88
|
+
|
89
|
+
def template_part_mark(name, id)
|
90
|
+
"<!--[#{name}:#{id}]-->\n"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Base class for commands which handle generator actions in reverse, such as Destroy.
|
95
|
+
class RewindBase < Base
|
96
|
+
# Rewind action manifest.
|
97
|
+
def invoke!
|
98
|
+
manifest.rewind(self)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# Create is the premier generator command. It copies files, creates
|
104
|
+
# directories, renders templates, and more.
|
105
|
+
class Create < Base
|
106
|
+
|
107
|
+
# Check whether the given class names are already taken by
|
108
|
+
# Ruby or Rails. In the future, expand to check other namespaces
|
109
|
+
# such as the rest of the user's app.
|
110
|
+
def class_collisions(*class_names)
|
111
|
+
class_names.flatten.each do |class_name|
|
112
|
+
# Convert to string to allow symbol arguments.
|
113
|
+
class_name = class_name.to_s
|
114
|
+
|
115
|
+
# Skip empty strings.
|
116
|
+
next if class_name.strip.empty?
|
117
|
+
|
118
|
+
# Split the class from its module nesting.
|
119
|
+
nesting = class_name.split('::')
|
120
|
+
name = nesting.pop
|
121
|
+
|
122
|
+
# Extract the last Module in the nesting.
|
123
|
+
last = nesting.inject(Object) { |last, nest|
|
124
|
+
break unless last.const_defined?(nest)
|
125
|
+
last.const_get(nest)
|
126
|
+
}
|
127
|
+
|
128
|
+
# If the last Module exists, check whether the given
|
129
|
+
# class exists and raise a collision if so.
|
130
|
+
if last and last.const_defined?(name.camelize)
|
131
|
+
raise_class_collision(class_name)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Copy a file from source to destination with collision checking.
|
137
|
+
#
|
138
|
+
# The file_options hash accepts :chmod and :shebang options.
|
139
|
+
# :chmod sets the permissions of the destination file:
|
140
|
+
# file 'config/empty.log', 'log/test.log', :chmod => 0664
|
141
|
+
# :shebang sets the #!/usr/bin/ruby line for scripts
|
142
|
+
# file 'bin/generate.rb', 'script/generate', :chmod => 0755, :shebang => '/usr/bin/env ruby'
|
143
|
+
#
|
144
|
+
# Collisions are handled by checking whether the destination file
|
145
|
+
# exists and either skipping the file, forcing overwrite, or asking
|
146
|
+
# the user what to do.
|
147
|
+
def file(relative_source, relative_destination, file_options = {})
|
148
|
+
# Determine full paths for source and destination files.
|
149
|
+
source = source_path(relative_source)
|
150
|
+
destination = destination_path(relative_destination)
|
151
|
+
|
152
|
+
# Check for and resolve file collisions.
|
153
|
+
if File.exists?(destination)
|
154
|
+
|
155
|
+
# Make a choice whether to overwrite the file. :force and
|
156
|
+
# :skip already have their mind made up, but give :ask a shot.
|
157
|
+
choice = case options[:collision].to_sym #|| :ask
|
158
|
+
when :ask then force_file_collision?(relative_destination)
|
159
|
+
when :force then :force
|
160
|
+
when :skip then :skip
|
161
|
+
else raise "Invalid collision option: #{options[:collision].inspect}"
|
162
|
+
end
|
163
|
+
|
164
|
+
# Take action based on our choice. Bail out if we chose to
|
165
|
+
# skip the file; otherwise, log our transgression and continue.
|
166
|
+
case choice
|
167
|
+
when :force then logger.force(relative_destination)
|
168
|
+
when :skip then return(logger.skip(relative_destination))
|
169
|
+
else raise "Invalid collision choice: #{choice}.inspect"
|
170
|
+
end
|
171
|
+
|
172
|
+
# File doesn't exist so log its unbesmirched creation.
|
173
|
+
else
|
174
|
+
logger.create relative_destination
|
175
|
+
end
|
176
|
+
|
177
|
+
# If we're pretending, back off now.
|
178
|
+
return if options[:pretend]
|
179
|
+
|
180
|
+
# Write destination file with optional shebang. Yield for content
|
181
|
+
# if block given so templaters may render the source file. If a
|
182
|
+
# shebang is requested, replace the existing shebang or insert a
|
183
|
+
# new one.
|
184
|
+
File.open(destination, 'w') do |df|
|
185
|
+
File.open(source) do |sf|
|
186
|
+
if block_given?
|
187
|
+
df.write(yield(sf))
|
188
|
+
else
|
189
|
+
line = sf.gets
|
190
|
+
if file_options[:shebang]
|
191
|
+
df.puts("#!#{file_options[:shebang]}")
|
192
|
+
df.puts(line) if line !~ /^#!/
|
193
|
+
else
|
194
|
+
df.puts(line)
|
195
|
+
end
|
196
|
+
df.write(sf.read)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Optionally change permissions.
|
202
|
+
if file_options[:chmod]
|
203
|
+
FileUtils.chmod(file_options[:chmod], destination)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Generate a file for a Rails application using an ERuby template.
|
208
|
+
# Looks up and evalutes a template by name and writes the result.
|
209
|
+
#
|
210
|
+
# The ERB template uses explicit trim mode to best control the
|
211
|
+
# proliferation of whitespace in generated code. <%- trims leading
|
212
|
+
# whitespace; -%> trims trailing whitespace including one newline.
|
213
|
+
#
|
214
|
+
# A hash of template options may be passed as the last argument.
|
215
|
+
# The options accepted by the file are accepted as well as :assigns,
|
216
|
+
# a hash of variable bindings. Example:
|
217
|
+
# template 'foo', 'bar', :assigns => { :action => 'view' }
|
218
|
+
#
|
219
|
+
# Template is implemented in terms of file. It calls file with a
|
220
|
+
# block which takes a file handle and returns its rendered contents.
|
221
|
+
def template(relative_source, relative_destination, template_options = {})
|
222
|
+
file(relative_source, relative_destination, template_options) do |file|
|
223
|
+
# Evaluate any assignments in a temporary, throwaway binding.
|
224
|
+
vars = template_options[:assigns] || {}
|
225
|
+
b = binding
|
226
|
+
vars.each { |k,v| eval "#{k} = vars[:#{k}] || vars['#{k}']", b }
|
227
|
+
|
228
|
+
# Render the source file with the temporary binding.
|
229
|
+
ERB.new(file.read, nil, '-').result(b)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def complex_template(relative_source, relative_destination, template_options = {})
|
234
|
+
options = template_options.dup
|
235
|
+
options[:assigns] ||= {}
|
236
|
+
options[:assigns]['template_for_inclusion'] = render_template_part(template_options)
|
237
|
+
template(relative_source, relative_destination, options)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Create a directory including any missing parent directories.
|
241
|
+
# Always directories which exist.
|
242
|
+
def directory(relative_path)
|
243
|
+
path = destination_path(relative_path)
|
244
|
+
if File.exists?(path)
|
245
|
+
logger.exists relative_path
|
246
|
+
else
|
247
|
+
logger.create relative_path
|
248
|
+
FileUtils.mkdir_p(path) unless options[:pretend]
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Display a README.
|
253
|
+
def readme(*relative_sources)
|
254
|
+
relative_sources.flatten.each do |relative_source|
|
255
|
+
logger.readme relative_source
|
256
|
+
puts File.read(source_path(relative_source)) unless options[:pretend]
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
# Raise a usage error with an informative WordNet suggestion.
|
262
|
+
# Thanks to Florian Gross (flgr).
|
263
|
+
def raise_class_collision(class_name)
|
264
|
+
message = <<end_message
|
265
|
+
The name '#{class_name}' is reserved by Ruby on Rails.
|
266
|
+
Please choose an alternative and run this generator again.
|
267
|
+
end_message
|
268
|
+
if suggest = find_synonyms(class_name)
|
269
|
+
message << "\n Suggestions: \n\n"
|
270
|
+
message << suggest.join("\n")
|
271
|
+
end
|
272
|
+
raise UsageError, message
|
273
|
+
end
|
274
|
+
|
275
|
+
SYNONYM_LOOKUP_URI = "http://wordnet.princeton.edu/cgi-bin/webwn2.0?stage=2&word=%s&posnumber=1&searchtypenumber=2&senses=&showglosses=1"
|
276
|
+
|
277
|
+
# Look up synonyms on WordNet. Thanks to Florian Gross (flgr).
|
278
|
+
def find_synonyms(word)
|
279
|
+
require 'open-uri'
|
280
|
+
require 'timeout'
|
281
|
+
timeout(5) do
|
282
|
+
open(SYNONYM_LOOKUP_URI % word) do |stream|
|
283
|
+
data = stream.read.gsub(" ", " ").gsub("<BR>", "")
|
284
|
+
data.scan(/^Sense \d+\n.+?\n\n/m)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
rescue Exception
|
288
|
+
return nil
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
# Undo the actions performed by a generator. Rewind the action
|
294
|
+
# manifest and attempt to completely erase the results of each action.
|
295
|
+
class Destroy < RewindBase
|
296
|
+
# Remove a file if it exists and is a file.
|
297
|
+
def file(relative_source, relative_destination, options = {})
|
298
|
+
destination = destination_path(relative_destination)
|
299
|
+
if File.exists?(destination)
|
300
|
+
logger.rm relative_destination
|
301
|
+
FileUtils.rm(destination) unless options[:pretend]
|
302
|
+
else
|
303
|
+
logger.missing relative_destination
|
304
|
+
return
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
# Templates are deleted just like files and the actions take the
|
309
|
+
# same parameters, so simply alias the file method.
|
310
|
+
alias_method :template, :file
|
311
|
+
|
312
|
+
# Remove each directory in the given path from right to left.
|
313
|
+
# Remove each subdirectory if it exists and is a directory.
|
314
|
+
def directory(relative_path)
|
315
|
+
parts = relative_path.split('/')
|
316
|
+
until parts.empty?
|
317
|
+
partial = File.join(parts)
|
318
|
+
path = destination_path(partial)
|
319
|
+
if File.exists?(path)
|
320
|
+
if Dir[File.join(path, '*')].empty?
|
321
|
+
logger.rmdir partial
|
322
|
+
FileUtils.rmdir(path) unless options[:pretend]
|
323
|
+
else
|
324
|
+
logger.notempty partial
|
325
|
+
end
|
326
|
+
else
|
327
|
+
logger.missing partial
|
328
|
+
end
|
329
|
+
parts.pop
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def complex_template(*args)
|
334
|
+
# nothing should be done here
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# List a generator's action manifest.
|
340
|
+
class List < Base
|
341
|
+
def dependency(generator_name, args, options = {})
|
342
|
+
logger.dependency "#{generator_name}(#{args.join(', ')}, #{options.inspect})"
|
343
|
+
end
|
344
|
+
|
345
|
+
def class_collisions(*class_names)
|
346
|
+
logger.class_collisions class_names.join(', ')
|
347
|
+
end
|
348
|
+
|
349
|
+
def file(relative_source, relative_destination, options = {})
|
350
|
+
logger.file relative_destination
|
351
|
+
end
|
352
|
+
|
353
|
+
def template(relative_source, relative_destination, options = {})
|
354
|
+
logger.template relative_destination
|
355
|
+
end
|
356
|
+
|
357
|
+
def complex_template(relative_source, relative_destination, options = {})
|
358
|
+
logger.template "#{options[:insert]} inside #{relative_destination}"
|
359
|
+
end
|
360
|
+
|
361
|
+
def directory(relative_path)
|
362
|
+
logger.directory "#{destination_path(relative_path)}/"
|
363
|
+
end
|
364
|
+
|
365
|
+
def readme(*args)
|
366
|
+
logger.readme args.join(', ')
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Update generator's action manifest.
|
371
|
+
class Update < Create
|
372
|
+
def file(relative_source, relative_destination, options = {})
|
373
|
+
# logger.file relative_destination
|
374
|
+
end
|
375
|
+
|
376
|
+
def template(relative_source, relative_destination, options = {})
|
377
|
+
# logger.template relative_destination
|
378
|
+
end
|
379
|
+
|
380
|
+
def complex_template(relative_source, relative_destination, template_options = {})
|
381
|
+
|
382
|
+
begin
|
383
|
+
dest_file = destination_path(relative_destination)
|
384
|
+
source_to_update = File.readlines(dest_file).join
|
385
|
+
rescue Errno::ENOENT
|
386
|
+
logger.missing relative_destination
|
387
|
+
return
|
388
|
+
end
|
389
|
+
|
390
|
+
logger.refreshing "#{template_options[:insert].gsub(/\.rhtml/,'')} inside #{relative_destination}"
|
391
|
+
|
392
|
+
begin_mark = Regexp.quote(template_part_mark(template_options[:begin_mark], template_options[:mark_id]))
|
393
|
+
end_mark = Regexp.quote(template_part_mark(template_options[:end_mark], template_options[:mark_id]))
|
394
|
+
|
395
|
+
# Refreshing inner part of the template with freshly rendered part.
|
396
|
+
rendered_part = render_template_part(template_options)
|
397
|
+
source_to_update.gsub!(/#{begin_mark}.*?#{end_mark}/m, rendered_part)
|
398
|
+
|
399
|
+
File.open(dest_file, 'w') { |file| file.write(source_to_update) }
|
400
|
+
end
|
401
|
+
|
402
|
+
def directory(relative_path)
|
403
|
+
# logger.directory "#{destination_path(relative_path)}/"
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Description:
|
2
|
+
The 'rails' command creates a new Rails application with a default
|
3
|
+
directory structure and configuration at the path you specify.
|
4
|
+
|
5
|
+
Example:
|
6
|
+
rails ~/Code/Ruby/weblog
|
7
|
+
|
8
|
+
This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
|
9
|
+
See the README in the newly created application to get going.
|
10
|
+
|
11
|
+
WARNING:
|
12
|
+
Only specify --without-gems if you did not use gems to install Rails.
|
13
|
+
Your application will expect to find activerecord, actionpack, and
|
14
|
+
actionmailer directories in the vendor directory. A popular way to track
|
15
|
+
the bleeding edge of Rails development is to checkout from source control
|
16
|
+
directly to the vendor directory. See http://dev.rubyonrails.com
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class AppGenerator < Rails::Generator::Base
|
4
|
+
DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
|
5
|
+
Config::CONFIG['ruby_install_name'])
|
6
|
+
|
7
|
+
default_options :gem => true, :shebang => DEFAULT_SHEBANG
|
8
|
+
mandatory_options :source => "#{File.dirname(__FILE__)}/../../../../.."
|
9
|
+
|
10
|
+
def initialize(runtime_args, runtime_options = {})
|
11
|
+
super
|
12
|
+
usage if args.empty?
|
13
|
+
@destination_root = args.shift
|
14
|
+
end
|
15
|
+
|
16
|
+
def manifest
|
17
|
+
script_options = { :chmod => 0755, :shebang => options[:shebang] }
|
18
|
+
|
19
|
+
record do |m|
|
20
|
+
# Root directory and all subdirectories.
|
21
|
+
m.directory ''
|
22
|
+
BASEDIRS.each { |path| m.directory path }
|
23
|
+
|
24
|
+
# Root
|
25
|
+
m.file "fresh_rakefile", "Rakefile"
|
26
|
+
m.file "README", "README"
|
27
|
+
m.file "CHANGELOG", "CHANGELOG"
|
28
|
+
|
29
|
+
# Application
|
30
|
+
m.template "helpers/application.rb", "app/controllers/application.rb"
|
31
|
+
m.template "helpers/application_helper.rb", "app/helpers/application_helper.rb"
|
32
|
+
m.template "helpers/test_helper.rb", "test/test_helper.rb"
|
33
|
+
|
34
|
+
# database.yml and .htaccess
|
35
|
+
m.template "configs/database.yml", "config/database.yml"
|
36
|
+
m.template "configs/routes.rb", "config/routes.rb"
|
37
|
+
m.template "configs/apache.conf", "public/.htaccess"
|
38
|
+
|
39
|
+
# Environments
|
40
|
+
if options[:gem]
|
41
|
+
m.file "environments/shared_for_gem.rb", "config/environment.rb"
|
42
|
+
else
|
43
|
+
m.file "environments/shared.rb", "config/environment.rb"
|
44
|
+
end
|
45
|
+
m.file "environments/production.rb", "config/environments/production.rb"
|
46
|
+
m.file "environments/development.rb", "config/environments/development.rb"
|
47
|
+
m.file "environments/test.rb", "config/environments/test.rb"
|
48
|
+
|
49
|
+
# Scripts
|
50
|
+
%w(console console_sandbox.rb destroy generate server).each do |file|
|
51
|
+
m.file "bin/#{file}", "script/#{file}", script_options
|
52
|
+
end
|
53
|
+
if options[:gem]
|
54
|
+
m.file "bin/breakpointer_for_gem", "script/breakpointer", script_options
|
55
|
+
else
|
56
|
+
m.file "bin/breakpointer", "script/breakpointer", script_options
|
57
|
+
end
|
58
|
+
|
59
|
+
# Dispatches
|
60
|
+
m.file "dispatches/dispatch.rb", "public/dispatch.rb", script_options
|
61
|
+
m.file "dispatches/dispatch.rb", "public/dispatch.cgi", script_options
|
62
|
+
m.file "dispatches/dispatch.fcgi", "public/dispatch.fcgi", script_options
|
63
|
+
|
64
|
+
# HTML files
|
65
|
+
%w(404 500 index).each do |file|
|
66
|
+
m.template "html/#{file}.html", "public/#{file}.html"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Docs
|
70
|
+
m.file "doc/README_FOR_APP", "doc/README_FOR_APP"
|
71
|
+
|
72
|
+
# Logs
|
73
|
+
%w(server production development test).each { |file|
|
74
|
+
m.file "configs/empty.log", "log/#{file}.log", :chmod => 0666
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
def banner
|
81
|
+
"Usage: #{$0} /path/to/your/app [options]"
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_options!(opt)
|
85
|
+
opt.separator ''
|
86
|
+
opt.separator 'Options:'
|
87
|
+
opt.on("--ruby [#{DEFAULT_SHEBANG}]",
|
88
|
+
"Path to the Ruby binary of your choice.") { |options[:shebang]| }
|
89
|
+
opt.on("--without-gems",
|
90
|
+
"Don't use the Rails gems for your app.",
|
91
|
+
"WARNING: see note below.") { |options[:gem]| }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# Installation skeleton. Intermediate directories are automatically
|
96
|
+
# created so don't sweat their absence here.
|
97
|
+
BASEDIRS = %w(
|
98
|
+
app/apis
|
99
|
+
app/controllers
|
100
|
+
app/helpers
|
101
|
+
app/models
|
102
|
+
app/views/layouts
|
103
|
+
config/environments
|
104
|
+
components
|
105
|
+
db
|
106
|
+
doc
|
107
|
+
lib
|
108
|
+
log
|
109
|
+
public/images
|
110
|
+
public/javascripts
|
111
|
+
public/stylesheets
|
112
|
+
script
|
113
|
+
test/fixtures
|
114
|
+
test/functional
|
115
|
+
test/mocks/development
|
116
|
+
test/mocks/testing
|
117
|
+
test/unit
|
118
|
+
vendor
|
119
|
+
)
|
120
|
+
end
|