vmc 0.3.12 → 0.3.13.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/lib/cli/commands/apps.rb +29 -5
  2. data/lib/cli/commands/misc.rb +1 -1
  3. data/lib/cli/commands/user.rb +1 -1
  4. data/lib/cli/config.rb +25 -8
  5. data/lib/cli/frameworks.rb +25 -5
  6. data/lib/cli/version.rb +1 -1
  7. data/lib/vmc/client.rb +6 -2
  8. data/spec/assets/grails/grails.war +0 -0
  9. data/spec/assets/java_web/java_web.war +0 -0
  10. data/spec/assets/lift/lift.war +0 -0
  11. data/spec/assets/node/app.js +16 -0
  12. data/spec/assets/rails3/Gemfile +8 -0
  13. data/spec/assets/rails3/README +256 -0
  14. data/spec/assets/rails3/Rakefile +7 -0
  15. data/spec/assets/rails3/app/controllers/application_controller.rb +3 -0
  16. data/spec/assets/rails3/app/controllers/root_controller.rb +13 -0
  17. data/spec/assets/rails3/app/helpers/application_helper.rb +2 -0
  18. data/spec/assets/rails3/app/helpers/root_helper.rb +2 -0
  19. data/spec/assets/rails3/app/models/widget.rb +2 -0
  20. data/spec/assets/rails3/app/views/layouts/application.html.erb +11 -0
  21. data/spec/assets/rails3/app/views/root/index.html.erb +5 -0
  22. data/spec/assets/rails3/config.ru +4 -0
  23. data/spec/assets/rails3/config/application.rb +42 -0
  24. data/spec/assets/rails3/config/boot.rb +13 -0
  25. data/spec/assets/rails3/config/database.yml +12 -0
  26. data/spec/assets/rails3/config/environment.rb +5 -0
  27. data/spec/assets/rails3/config/environments/development.rb +26 -0
  28. data/spec/assets/rails3/config/environments/production.rb +49 -0
  29. data/spec/assets/rails3/config/environments/test.rb +35 -0
  30. data/spec/assets/rails3/config/initializers/backtrace_silencers.rb +7 -0
  31. data/spec/assets/rails3/config/initializers/inflections.rb +10 -0
  32. data/spec/assets/rails3/config/initializers/mime_types.rb +5 -0
  33. data/spec/assets/rails3/config/initializers/secret_token.rb +7 -0
  34. data/spec/assets/rails3/config/initializers/session_store.rb +8 -0
  35. data/spec/assets/rails3/config/locales/en.yml +5 -0
  36. data/spec/assets/rails3/config/routes.rb +61 -0
  37. data/spec/assets/rails3/db/migrate/20101108182500_create_widgets.rb +13 -0
  38. data/spec/assets/rails3/db/schema.rb +21 -0
  39. data/spec/assets/rails3/db/seeds.rb +7 -0
  40. data/spec/assets/rails3/public/404.html +26 -0
  41. data/spec/assets/rails3/public/422.html +26 -0
  42. data/spec/assets/rails3/public/500.html +26 -0
  43. data/spec/assets/rails3/public/favicon.ico +0 -0
  44. data/spec/assets/rails3/public/images/rails.png +0 -0
  45. data/spec/assets/rails3/public/javascripts/application.js +0 -0
  46. data/spec/assets/rails3/public/robots.txt +5 -0
  47. data/spec/assets/rails3/script/rails +6 -0
  48. data/spec/assets/rails3/test/functional/root_controller_test.rb +14 -0
  49. data/spec/assets/rails3/test/performance/browsing_test.rb +9 -0
  50. data/spec/assets/rails3/test/test_helper.rb +13 -0
  51. data/spec/assets/rails3/test/unit/helpers/root_helper_test.rb +4 -0
  52. data/spec/assets/rails3/test/unit/widget_test.rb +12 -0
  53. data/spec/assets/service_gateway_fail.txt +9 -0
  54. data/spec/assets/sinatra/foo.rb +13 -0
  55. data/spec/assets/spring/spring.war +0 -0
  56. data/spec/unit/client_spec.rb +13 -0
  57. data/spec/unit/frameworks_spec.rb +75 -0
  58. metadata +130 -77
@@ -202,10 +202,16 @@ module VMC::Cli::Command
202
202
  app = client.app_info(appname)
203
203
  services_to_delete = []
204
204
  app_services = app[:services]
205
+ services_apps_hash = provisioned_services_apps_hash
205
206
  app_services.each { |service|
206
207
  del_service = force && no_prompt ? 'Y' : 'N'
207
208
  unless no_prompt || force
208
- del_service = ask("Provisioned service [#{service}] detected, would you like to delete it? [yN]: ")
209
+ apps_using_service = services_apps_hash[service].reject!{ |app| app == appname}
210
+ if apps_using_service.size > 0
211
+ del_service = ask("Provisioned service [#{service}] is being used by #{apps_using_service.entries}, would you still like to delete it? [yN]: ")
212
+ else
213
+ del_service = ask("Provisioned service [#{service}] detected, would you like to delete it? [yN]: ")
214
+ end
209
215
  end
210
216
  services_to_delete << service if del_service.upcase == 'Y'
211
217
  }
@@ -213,10 +219,12 @@ module VMC::Cli::Command
213
219
  client.delete_app(appname)
214
220
  display 'OK'.green
215
221
 
216
- services_to_delete.each do |s|
217
- display "Deleting service [#{s}]: ", false
218
- client.delete_service(s)
219
- display 'OK'.green
222
+ unless services_to_delete.length == 0
223
+ services_to_delete.each do |s|
224
+ display "Deleting service [#{s}]: ", false
225
+ client.delete_service(s)
226
+ display 'OK'.green
227
+ end
220
228
  end
221
229
  end
222
230
 
@@ -697,6 +705,22 @@ module VMC::Cli::Command
697
705
  end
698
706
  end
699
707
 
708
+ def provisioned_services_apps_hash
709
+ apps = client.apps
710
+ services_apps_hash = {}
711
+ apps.each {|app|
712
+ app[:services].each { |svc|
713
+ svc_apps = services_apps_hash[svc]
714
+ unless svc_apps
715
+ svc_apps = Set.new
716
+ services_apps_hash[svc] = svc_apps
717
+ end
718
+ svc_apps.add(app[:name])
719
+ } unless app[:services] == nil
720
+ }
721
+ services_apps_hash
722
+ end
723
+
700
724
  def check_app_limit
701
725
  usage = client_info[:usage]
702
726
  limits = client_info[:limits]
@@ -30,7 +30,7 @@ module VMC::Cli::Command
30
30
  client = VMC::Client.new(target_url)
31
31
  unless client.target_valid?
32
32
  if prompt_ok
33
- display "Host is not valid: '#{target_url}'".red
33
+ display "Host is not available or is not valid: '#{target_url}'".red
34
34
  show_response = ask "Would you like see the response [yN]? "
35
35
  display "\n<<<\n#{client.raw_info}\n>>>\n" if show_response.upcase == 'Y'
36
36
  end
@@ -12,7 +12,7 @@ module VMC::Cli::Command
12
12
  def login(email=nil)
13
13
  email = @options[:email] unless email
14
14
  password = @options[:password]
15
- tries = 0
15
+ tries ||= 0
16
16
  email = ask("Email: ") unless no_prompt || email
17
17
  password = ask("Password: ") {|q| q.echo = '*'} unless no_prompt || password
18
18
  err "Need a valid email" unless email
data/lib/cli/config.rb CHANGED
@@ -26,7 +26,7 @@ module VMC::Cli
26
26
  return @target_url if @target_url
27
27
  target_file = File.expand_path(TARGET_FILE)
28
28
  if File.exists? target_file
29
- @target_url = File.read(target_file).strip!
29
+ @target_url = lock_and_read(target_file).strip!
30
30
  ha = @target_url.split('.')
31
31
  ha.shift
32
32
  @suggest_url = ha.join('.')
@@ -42,14 +42,13 @@ module VMC::Cli
42
42
 
43
43
  def store_target(target_host)
44
44
  target_file = File.expand_path(TARGET_FILE)
45
- File.open(target_file, 'w+') { |f| f.puts target_host }
46
- FileUtils.chmod 0600, target_file
45
+ lock_and_write(target_file, target_host)
47
46
  end
48
47
 
49
48
  def all_tokens
50
49
  token_file = File.expand_path(TOKEN_FILE)
51
50
  return nil unless File.exists? token_file
52
- contents = File.read(token_file).strip
51
+ contents = lock_and_read(token_file).strip
53
52
  JSON.parse(contents)
54
53
  end
55
54
 
@@ -69,20 +68,19 @@ module VMC::Cli
69
68
  tokens = all_tokens || {}
70
69
  tokens[target_url] = token
71
70
  token_file = File.expand_path(TOKEN_FILE)
72
- File.open(token_file, 'w+') { |f| f.write(tokens.to_json) }
73
- FileUtils.chmod 0600, token_file
71
+ lock_and_write(token_file, tokens.to_json)
74
72
  end
75
73
 
76
74
  def instances
77
75
  instances_file = File.expand_path(INSTANCES_FILE)
78
76
  return nil unless File.exists? instances_file
79
- contents = File.read(instances_file).strip
77
+ contents = lock_and_read(instances_file).strip
80
78
  JSON.parse(contents)
81
79
  end
82
80
 
83
81
  def store_instances(instances)
84
82
  instances_file = File.expand_path(INSTANCES_FILE)
85
- File.open(instances_file, 'w') { |f| f.write(instances.to_json) }
83
+ lock_and_write(instances_file, instances.to_json)
86
84
  end
87
85
 
88
86
  def aliases
@@ -100,6 +98,25 @@ module VMC::Cli
100
98
  File.open(aliases_file, 'wb') {|f| f.write(aliases.to_yaml)}
101
99
  end
102
100
 
101
+ def lock_and_read(file)
102
+ File.open(file, "r") {|f|
103
+ f.flock(File::LOCK_EX)
104
+ contents = f.read
105
+ f.flock(File::LOCK_UN)
106
+ contents
107
+ }
108
+ end
109
+
110
+ def lock_and_write(file, contents)
111
+ File.open(file, File::RDWR | File::CREAT, 0600) {|f|
112
+ f.flock(File::LOCK_EX)
113
+ f.rewind
114
+ f.puts contents
115
+ f.flush
116
+ f.truncate(f.pos)
117
+ f.flock(File::LOCK_UN)
118
+ }
119
+ end
103
120
  end
104
121
 
105
122
  def initialize(work_dir = Dir.pwd)
@@ -10,11 +10,13 @@ module VMC::Cli
10
10
  'Spring' => ['spring', { :mem => '512M', :description => 'Java SpringSource Spring Application'}],
11
11
  'Grails' => ['grails', { :mem => '512M', :description => 'Java SpringSource Grails Application'}],
12
12
  'Lift' => ['lift', { :mem => '512M', :description => 'Scala Lift Application'}],
13
- 'Roo' => ['spring', { :mem => '512M', :description => 'Java SpringSource Roo Application'}],
14
13
  'JavaWeb' => ['spring', { :mem => '512M', :description => 'Java Web Application'}],
15
14
  'Sinatra' => ['sinatra', { :mem => '128M', :description => 'Sinatra Application'}],
16
15
  'Node' => ['node', { :mem => '64M', :description => 'Node.js Application'}],
17
- 'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}]
16
+ 'PHP' => ['php', { :mem => '128M', :description => 'PHP Application'}],
17
+ 'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}],
18
+ 'WSGI' => ['wsgi', { :mem => '64M', :description => 'Python WSGI Application'}],
19
+ 'Django' => ['django', { :mem => '128M', :description => 'Python Django Application'}],
18
20
  }
19
21
 
20
22
  class << self
@@ -35,9 +37,14 @@ module VMC::Cli
35
37
  return Framework.lookup('Rails')
36
38
 
37
39
  # Java
38
- elsif Dir.glob('*.war').first
40
+ elsif Dir.glob('*.war').first || File.exist?('WEB-INF/web.xml')
39
41
  war_file = Dir.glob('*.war').first
40
- contents = ZipUtil.entry_lines(war_file)
42
+
43
+ if war_file
44
+ contents = ZipUtil.entry_lines(war_file)
45
+ else
46
+ contents = Dir['**/*'].join("\n")
47
+ end
41
48
 
42
49
  # Spring/Lift Variations
43
50
  if contents =~ /WEB-INF\/lib\/grails-web.*\.jar/
@@ -51,7 +58,6 @@ module VMC::Cli
51
58
  else
52
59
  return Framework.lookup('JavaWeb')
53
60
  end
54
-
55
61
  # Simple Ruby Apps
56
62
  elsif !Dir.glob('*.rb').empty?
57
63
  matched_file = nil
@@ -74,9 +80,23 @@ module VMC::Cli
74
80
  return Framework.lookup('Node')
75
81
  end
76
82
 
83
+ # PHP
84
+ elsif !Dir.glob('*.php').empty?
85
+ return Framework.lookup('PHP')
86
+
77
87
  # Erlang/OTP using Rebar
78
88
  elsif !Dir.glob('releases/*/*.rel').empty? && !Dir.glob('releases/*/*.boot').empty?
79
89
  return Framework.lookup('Erlang/OTP Rebar')
90
+
91
+ # Python Django
92
+ # XXX: not all django projects keep settings.py in top-level directory
93
+ elsif File.exist?('manage.py') && File.exist?('settings.py')
94
+ return Framework.lookup('Django')
95
+
96
+ # Python
97
+ elsif !Dir.glob('wsgi.py').empty?
98
+ return Framework.lookup('WSGI')
99
+
80
100
  end
81
101
  end
82
102
  nil
data/lib/cli/version.rb CHANGED
@@ -2,6 +2,6 @@ module VMC
2
2
  module Cli
3
3
  # This version number is used as the RubyGem release version.
4
4
  # The internal VMC version number is VMC::VERSION.
5
- VERSION = '0.3.12'
5
+ VERSION = '0.3.13.beta.1'
6
6
  end
7
7
  end
data/lib/vmc/client.rb CHANGED
@@ -25,7 +25,7 @@ class VMC::Client
25
25
  attr_accessor :trace
26
26
 
27
27
  # Error codes
28
- VMC_HTTP_ERROR_CODES = [ 400, 403, 404, 500 ]
28
+ VMC_HTTP_ERROR_CODES = [ 400, 500 ]
29
29
 
30
30
  # Errors
31
31
  class BadTarget < RuntimeError; end
@@ -369,7 +369,7 @@ class VMC::Client
369
369
  }
370
370
  status, body, response_headers = perform_http_request(req)
371
371
 
372
- if VMC_HTTP_ERROR_CODES.include?(status)
372
+ if request_failed?(status)
373
373
  # FIXME, old cc returned 400 on not found for file access
374
374
  err = (status == 404 || status == 400) ? NotFound : TargetError
375
375
  raise err, parse_error_message(status, body)
@@ -380,6 +380,10 @@ class VMC::Client
380
380
  raise BadTarget, "Cannot access target (%s)" % [ e.message ]
381
381
  end
382
382
 
383
+ def request_failed?(status)
384
+ VMC_HTTP_ERROR_CODES.detect{|error_code| status >= error_code}
385
+ end
386
+
383
387
  def perform_http_request(req)
384
388
  proxy_uri = URI.parse(req[:url]).find_proxy()
385
389
  RestClient.proxy = proxy_uri.to_s if proxy_uri
Binary file
Binary file
Binary file
@@ -0,0 +1,16 @@
1
+ var http = require('http');
2
+ var url = require('url');
3
+
4
+ HOST = null;
5
+
6
+ var host = process.env.VCAP_APP_HOST || 'localhost';
7
+ var port = process.env.VCAP_APP_PORT || 3000
8
+
9
+ http.createServer(function (req, res) {
10
+ res.writeHead(200, {'Content-Type': 'text/html'});
11
+ res.write('<h1>Hello from the Cloud! ');
12
+ res.write('via: ' + host + ':' + port);
13
+ res.end('</h1>');
14
+ }).listen(port, null);
15
+
16
+ console.log('Server running at http://' + host + ':' + port + '/');
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+ gem 'rails', '~> 3.0.5'
3
+ # Without any bound services, app runs on sqlite3
4
+ gem 'sqlite3'
5
+ #.. but may also be staged with mysql
6
+ gem 'mysql2'
7
+ gem 'thin'
8
+ gem 'ffi' # let's make it challenging
@@ -0,0 +1,256 @@
1
+ == Welcome to Rails
2
+
3
+ Rails is a web-application framework that includes everything needed to create
4
+ database-backed web applications according to the Model-View-Control pattern.
5
+
6
+ This pattern splits the view (also called the presentation) into "dumb"
7
+ templates that are primarily responsible for inserting pre-built data in between
8
+ HTML tags. The model contains the "smart" domain objects (such as Account,
9
+ Product, Person, Post) that holds all the business logic and knows how to
10
+ persist themselves to a database. The controller handles the incoming requests
11
+ (such as Save New Account, Update Product, Show Post) by manipulating the model
12
+ and directing data to the view.
13
+
14
+ In Rails, the model is handled by what's called an object-relational mapping
15
+ layer entitled Active Record. This layer allows you to present the data from
16
+ database rows as objects and embellish these data objects with business logic
17
+ methods. You can read more about Active Record in
18
+ link:files/vendor/rails/activerecord/README.html.
19
+
20
+ The controller and view are handled by the Action Pack, which handles both
21
+ layers by its two parts: Action View and Action Controller. These two layers
22
+ are bundled in a single package due to their heavy interdependence. This is
23
+ unlike the relationship between the Active Record and Action Pack that is much
24
+ more separate. Each of these packages can be used independently outside of
25
+ Rails. You can read more about Action Pack in
26
+ link:files/vendor/rails/actionpack/README.html.
27
+
28
+
29
+ == Getting Started
30
+
31
+ 1. At the command prompt, create a new Rails application:
32
+ <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
33
+
34
+ 2. Change directory to <tt>myapp</tt> and start the web server:
35
+ <tt>cd myapp; rails server</tt> (run with --help for options)
36
+
37
+ 3. Go to http://localhost:3000/ and you'll see:
38
+ "Welcome aboard: You're riding Ruby on Rails!"
39
+
40
+ 4. Follow the guidelines to start developing your application. You can find
41
+ the following resources handy:
42
+
43
+ * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
44
+ * Ruby on Rails Tutorial Book: http://www.railstutorial.org/
45
+
46
+
47
+ == Debugging Rails
48
+
49
+ Sometimes your application goes wrong. Fortunately there are a lot of tools that
50
+ will help you debug it and get it back on the rails.
51
+
52
+ First area to check is the application log files. Have "tail -f" commands
53
+ running on the server.log and development.log. Rails will automatically display
54
+ debugging and runtime information to these files. Debugging info will also be
55
+ shown in the browser on requests from 127.0.0.1.
56
+
57
+ You can also log your own messages directly into the log file from your code
58
+ using the Ruby logger class from inside your controllers. Example:
59
+
60
+ class WeblogController < ActionController::Base
61
+ def destroy
62
+ @weblog = Weblog.find(params[:id])
63
+ @weblog.destroy
64
+ logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
65
+ end
66
+ end
67
+
68
+ The result will be a message in your log file along the lines of:
69
+
70
+ Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
71
+
72
+ More information on how to use the logger is at http://www.ruby-doc.org/core/
73
+
74
+ Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
75
+ several books available online as well:
76
+
77
+ * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
78
+ * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
79
+
80
+ These two books will bring you up to speed on the Ruby language and also on
81
+ programming in general.
82
+
83
+
84
+ == Debugger
85
+
86
+ Debugger support is available through the debugger command when you start your
87
+ Mongrel or WEBrick server with --debugger. This means that you can break out of
88
+ execution at any point in the code, investigate and change the model, and then,
89
+ resume execution! You need to install ruby-debug to run the server in debugging
90
+ mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
91
+
92
+ class WeblogController < ActionController::Base
93
+ def index
94
+ @posts = Post.find(:all)
95
+ debugger
96
+ end
97
+ end
98
+
99
+ So the controller will accept the action, run the first line, then present you
100
+ with a IRB prompt in the server window. Here you can do things like:
101
+
102
+ >> @posts.inspect
103
+ => "[#<Post:0x14a6be8
104
+ @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
105
+ #<Post:0x14a6620
106
+ @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
107
+ >> @posts.first.title = "hello from a debugger"
108
+ => "hello from a debugger"
109
+
110
+ ...and even better, you can examine how your runtime objects actually work:
111
+
112
+ >> f = @posts.first
113
+ => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
114
+ >> f.
115
+ Display all 152 possibilities? (y or n)
116
+
117
+ Finally, when you're ready to resume execution, you can enter "cont".
118
+
119
+
120
+ == Console
121
+
122
+ The console is a Ruby shell, which allows you to interact with your
123
+ application's domain model. Here you'll have all parts of the application
124
+ configured, just like it is when the application is running. You can inspect
125
+ domain models, change values, and save to the database. Starting the script
126
+ without arguments will launch it in the development environment.
127
+
128
+ To start the console, run <tt>rails console</tt> from the application
129
+ directory.
130
+
131
+ Options:
132
+
133
+ * Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
134
+ made to the database.
135
+ * Passing an environment name as an argument will load the corresponding
136
+ environment. Example: <tt>rails console production</tt>.
137
+
138
+ To reload your controllers and models after launching the console run
139
+ <tt>reload!</tt>
140
+
141
+ More information about irb can be found at:
142
+ link:http://www.rubycentral.com/pickaxe/irb.html
143
+
144
+
145
+ == dbconsole
146
+
147
+ You can go to the command line of your database directly through <tt>rails
148
+ dbconsole</tt>. You would be connected to the database with the credentials
149
+ defined in database.yml. Starting the script without arguments will connect you
150
+ to the development database. Passing an argument will connect you to a different
151
+ database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
152
+ PostgreSQL and SQLite 3.
153
+
154
+ == Description of Contents
155
+
156
+ The default directory structure of a generated Ruby on Rails application:
157
+
158
+ |-- app
159
+ | |-- controllers
160
+ | |-- helpers
161
+ | |-- models
162
+ | `-- views
163
+ | `-- layouts
164
+ |-- config
165
+ | |-- environments
166
+ | |-- initializers
167
+ | `-- locales
168
+ |-- db
169
+ |-- doc
170
+ |-- lib
171
+ | `-- tasks
172
+ |-- log
173
+ |-- public
174
+ | |-- images
175
+ | |-- javascripts
176
+ | `-- stylesheets
177
+ |-- script
178
+ | `-- performance
179
+ |-- test
180
+ | |-- fixtures
181
+ | |-- functional
182
+ | |-- integration
183
+ | |-- performance
184
+ | `-- unit
185
+ |-- tmp
186
+ | |-- cache
187
+ | |-- pids
188
+ | |-- sessions
189
+ | `-- sockets
190
+ `-- vendor
191
+ `-- plugins
192
+
193
+ app
194
+ Holds all the code that's specific to this particular application.
195
+
196
+ app/controllers
197
+ Holds controllers that should be named like weblogs_controller.rb for
198
+ automated URL mapping. All controllers should descend from
199
+ ApplicationController which itself descends from ActionController::Base.
200
+
201
+ app/models
202
+ Holds models that should be named like post.rb. Models descend from
203
+ ActiveRecord::Base by default.
204
+
205
+ app/views
206
+ Holds the template files for the view that should be named like
207
+ weblogs/index.html.erb for the WeblogsController#index action. All views use
208
+ eRuby syntax by default.
209
+
210
+ app/views/layouts
211
+ Holds the template files for layouts to be used with views. This models the
212
+ common header/footer method of wrapping views. In your views, define a layout
213
+ using the <tt>layout :default</tt> and create a file named default.html.erb.
214
+ Inside default.html.erb, call <% yield %> to render the view using this
215
+ layout.
216
+
217
+ app/helpers
218
+ Holds view helpers that should be named like weblogs_helper.rb. These are
219
+ generated for you automatically when using generators for controllers.
220
+ Helpers can be used to wrap functionality for your views into methods.
221
+
222
+ config
223
+ Configuration files for the Rails environment, the routing map, the database,
224
+ and other dependencies.
225
+
226
+ db
227
+ Contains the database schema in schema.rb. db/migrate contains all the
228
+ sequence of Migrations for your schema.
229
+
230
+ doc
231
+ This directory is where your application documentation will be stored when
232
+ generated using <tt>rake doc:app</tt>
233
+
234
+ lib
235
+ Application specific libraries. Basically, any kind of custom code that
236
+ doesn't belong under controllers, models, or helpers. This directory is in
237
+ the load path.
238
+
239
+ public
240
+ The directory available for the web server. Contains subdirectories for
241
+ images, stylesheets, and javascripts. Also contains the dispatchers and the
242
+ default HTML files. This should be set as the DOCUMENT_ROOT of your web
243
+ server.
244
+
245
+ script
246
+ Helper scripts for automation and generation.
247
+
248
+ test
249
+ Unit and functional tests along with fixtures. When using the rails generate
250
+ command, template test files will be generated for you and placed in this
251
+ directory.
252
+
253
+ vendor
254
+ External libraries that the application depends on. Also includes the plugins
255
+ subdirectory. If the app has frozen rails, those gems also go here, under
256
+ vendor/rails/. This directory is in the load path.