railties 3.0.20 → 3.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +36 -49
- data/README.rdoc +2 -1
- data/guides/assets/stylesheets/fixes.css +16 -0
- data/guides/rails_guides.rb +2 -2
- data/guides/rails_guides/generator.rb +8 -3
- data/guides/rails_guides/textile_extensions.rb +4 -2
- data/guides/source/2_2_release_notes.textile +3 -3
- data/guides/source/2_3_release_notes.textile +2 -2
- data/guides/source/3_0_release_notes.textile +14 -14
- data/guides/source/action_controller_overview.textile +54 -79
- data/guides/source/action_mailer_basics.textile +39 -9
- data/guides/source/action_view_overview.textile +257 -211
- data/guides/source/active_record_basics.textile +1 -1
- data/guides/source/active_record_querying.textile +217 -27
- data/guides/source/active_record_validations_callbacks.textile +94 -25
- data/guides/source/active_support_core_extensions.textile +109 -77
- data/guides/source/ajax_on_rails.textile +15 -150
- data/guides/source/api_documentation_guidelines.textile +12 -12
- data/guides/source/association_basics.textile +74 -60
- data/guides/source/caching_with_rails.textile +59 -60
- data/guides/source/command_line.textile +46 -47
- data/guides/source/configuring.textile +55 -37
- data/guides/source/contribute.textile +7 -7
- data/guides/source/contributing_to_ruby_on_rails.textile +14 -23
- data/guides/source/credits.html.erb +3 -3
- data/guides/source/debugging_rails_applications.textile +59 -46
- data/guides/source/form_helpers.textile +76 -31
- data/guides/source/generators.textile +39 -40
- data/guides/source/getting_started.textile +73 -94
- data/guides/source/i18n.textile +64 -58
- data/guides/source/index.html.erb +3 -3
- data/guides/source/initialization.textile +634 -3284
- data/guides/source/layout.html.erb +6 -7
- data/guides/source/layouts_and_rendering.textile +59 -60
- data/guides/source/migrations.textile +63 -59
- data/guides/source/nested_model_forms.textile +2 -2
- data/guides/source/performance_testing.textile +16 -16
- data/guides/source/plugins.textile +236 -1280
- data/guides/source/rails_application_templates.textile +37 -29
- data/guides/source/rails_on_rack.textile +4 -9
- data/guides/source/routing.textile +96 -75
- data/guides/source/ruby_on_rails_guides_guidelines.textile +19 -12
- data/guides/source/security.textile +57 -30
- data/guides/source/testing.textile +26 -24
- data/guides/w3c_validator.rb +2 -2
- data/lib/rails.rb +1 -7
- data/lib/rails/application.rb +46 -76
- data/lib/rails/application/bootstrap.rb +6 -11
- data/lib/rails/application/configuration.rb +43 -40
- data/lib/rails/application/finisher.rb +16 -4
- data/lib/rails/application/railties.rb +6 -24
- data/lib/rails/application/routes_reloader.rb +45 -0
- data/lib/rails/backtrace_cleaner.rb +1 -1
- data/lib/rails/cli.rb +7 -5
- data/lib/rails/commands.rb +27 -2
- data/lib/rails/commands/application.rb +14 -1
- data/lib/rails/commands/benchmarker.rb +3 -1
- data/lib/rails/commands/dbconsole.rb +2 -2
- data/lib/rails/commands/destroy.rb +3 -1
- data/lib/rails/commands/generate.rb +3 -1
- data/lib/rails/commands/plugin.rb +2 -7
- data/lib/rails/commands/plugin_new.rb +10 -0
- data/lib/rails/commands/profiler.rb +3 -1
- data/lib/rails/commands/server.rb +4 -0
- data/lib/rails/configuration.rb +8 -81
- data/lib/rails/console/app.rb +2 -2
- data/lib/rails/engine.rb +460 -78
- data/lib/rails/engine/configuration.rb +46 -49
- data/lib/rails/engine/railties.rb +33 -0
- data/lib/rails/generators.rb +11 -5
- data/lib/rails/generators/actions.rb +2 -27
- data/lib/rails/generators/app_base.rb +216 -0
- data/lib/rails/generators/base.rb +3 -2
- data/lib/rails/generators/erb/scaffold/templates/index.html.erb +1 -1
- data/lib/rails/generators/generated_attribute.rb +2 -1
- data/lib/rails/generators/migration.rb +6 -2
- data/lib/rails/generators/named_base.rb +79 -3
- data/lib/rails/generators/rails/app/app_generator.rb +44 -209
- data/lib/rails/generators/rails/app/templates/Gemfile +15 -31
- data/lib/rails/generators/rails/app/templates/README +2 -2
- data/lib/rails/generators/rails/app/templates/Rakefile +1 -1
- data/lib/rails/generators/rails/app/templates/{public → app/assets}/images/rails.png +0 -0
- data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +8 -0
- data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css +5 -0
- data/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/app/models/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +4 -4
- data/lib/rails/generators/rails/app/templates/config/application.rb +19 -3
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +4 -4
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml +11 -6
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml +3 -3
- data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +1 -2
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +14 -11
- data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt +12 -0
- data/lib/rails/generators/rails/app/templates/config/locales/en.yml +1 -1
- data/lib/rails/generators/rails/app/templates/config/routes.rb +1 -1
- data/lib/rails/generators/rails/app/templates/db/{seeds.rb → seeds.rb.tt} +2 -2
- data/lib/rails/generators/rails/app/templates/public/index.html +10 -8
- data/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/test/functional/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/test/integration/.empty_directory +0 -0
- data/lib/rails/generators/rails/app/templates/test/{test_helper.rb.tt → test_helper.rb} +0 -0
- data/lib/rails/generators/rails/app/templates/test/unit/.empty_directory +0 -0
- data/lib/rails/generators/rails/assets/USAGE +20 -0
- data/lib/rails/generators/rails/assets/assets_generator.rb +39 -0
- data/lib/rails/generators/rails/assets/templates/javascript.js +2 -0
- data/lib/rails/generators/rails/assets/templates/javascript.js.coffee +3 -0
- data/lib/rails/generators/rails/assets/templates/stylesheet.css +4 -0
- data/lib/rails/generators/rails/assets/templates/stylesheet.css.scss +5 -0
- data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
- data/lib/rails/generators/rails/controller/templates/controller.rb +2 -0
- data/lib/rails/generators/rails/generator/generator_generator.rb +2 -2
- data/lib/rails/generators/rails/generator/templates/templates/.empty_directory +0 -0
- data/lib/rails/generators/rails/helper/templates/helper.rb +2 -0
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +7 -0
- data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +4 -4
- data/lib/rails/generators/rails/plugin_new/USAGE +10 -0
- data/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +303 -0
- data/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec +9 -0
- data/lib/rails/generators/rails/plugin_new/templates/Gemfile +11 -0
- data/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE +20 -0
- data/lib/rails/generators/rails/plugin_new/templates/README.rdoc +3 -0
- data/lib/rails/generators/rails/plugin_new/templates/Rakefile +21 -0
- data/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt +4 -0
- data/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt +4 -0
- data/lib/rails/generators/rails/plugin_new/templates/app/models/.empty_directory +0 -0
- data/lib/rails/generators/rails/plugin_new/templates/config/routes.rb +6 -0
- data/lib/rails/generators/rails/plugin_new/templates/gitignore +6 -0
- data/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb +6 -0
- data/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +7 -0
- data/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake +4 -0
- data/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +16 -0
- data/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb +10 -0
- data/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb +4 -0
- data/lib/rails/generators/rails/plugin_new/templates/script/rails.tt +5 -0
- data/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb +7 -0
- data/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +12 -0
- data/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +10 -0
- data/lib/rails/generators/rails/resource/resource_generator.rb +2 -2
- data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +20 -1
- data/lib/rails/generators/rails/{stylesheets → scaffold}/templates/scaffold.css +0 -0
- data/lib/rails/generators/rails/scaffold/templates/scaffold.css.scss +58 -0
- data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +21 -19
- data/lib/rails/generators/resource_helpers.rb +3 -3
- data/lib/rails/generators/test_case.rb +2 -20
- data/lib/rails/generators/test_unit/controller/templates/functional_test.rb +5 -4
- data/lib/rails/generators/test_unit/helper/templates/helper_test.rb +2 -0
- data/lib/rails/generators/test_unit/integration/templates/integration_test.rb +3 -4
- data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb +5 -4
- data/lib/rails/generators/test_unit/model/templates/fixtures.yml +1 -1
- data/lib/rails/generators/test_unit/model/templates/unit_test.rb +5 -4
- data/lib/rails/generators/test_unit/observer/templates/unit_test.rb +5 -4
- data/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt +3 -4
- data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +7 -5
- data/lib/rails/info.rb +0 -1
- data/lib/rails/paths.rb +119 -65
- data/lib/rails/plugin.rb +18 -19
- data/lib/rails/rack/log_tailer.rb +1 -1
- data/lib/rails/railtie.rb +50 -47
- data/lib/rails/railtie/configurable.rb +20 -10
- data/lib/rails/railtie/configuration.rb +20 -19
- data/lib/rails/source_annotation_extractor.rb +5 -5
- data/lib/rails/tasks.rb +1 -0
- data/lib/rails/tasks/assets.rake +10 -0
- data/lib/rails/tasks/documentation.rake +2 -8
- data/lib/rails/tasks/engine.rake +69 -0
- data/lib/rails/tasks/framework.rake +4 -21
- data/lib/rails/tasks/misc.rake +1 -1
- data/lib/rails/tasks/routes.rake +2 -1
- data/lib/rails/test_help.rb +17 -1
- data/lib/rails/test_unit/railtie.rb +1 -1
- data/lib/rails/test_unit/testing.rake +8 -3
- data/lib/rails/version.rb +3 -3
- metadata +128 -100
- checksums.yaml +0 -7
- data/lib/rails/application/configurable.rb +0 -19
- data/lib/rails/console/sandbox.rb +0 -6
- data/lib/rails/deprecation.rb +0 -41
- data/lib/rails/engine/configurable.rb +0 -25
- data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml +0 -62
- data/lib/rails/generators/rails/app/templates/public/javascripts/application.js +0 -2
- data/lib/rails/generators/rails/app/templates/public/javascripts/controls.js +0 -965
- data/lib/rails/generators/rails/app/templates/public/javascripts/dragdrop.js +0 -974
- data/lib/rails/generators/rails/app/templates/public/javascripts/effects.js +0 -1123
- data/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js +0 -6001
- data/lib/rails/generators/rails/app/templates/public/javascripts/rails.js +0 -202
- data/lib/rails/generators/rails/stylesheets/USAGE +0 -5
- data/lib/rails/generators/rails/stylesheets/stylesheets_generator.rb +0 -9
- data/lib/rails/info_routes.rb +0 -3
@@ -22,7 +22,7 @@ TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails 3.
|
|
22
22
|
* The "RubyGems":http://rubyforge.org/frs/?group_id=126 packaging system
|
23
23
|
* A working installation of the "SQLite3 Database":http://www.sqlite.org
|
24
24
|
|
25
|
-
Rails is a web application framework running on the Ruby programming language. If you have no prior experience with Ruby, you will find a very steep learning curve diving straight into Rails.
|
25
|
+
Rails is a web application framework running on the Ruby programming language. If you have no prior experience with Ruby, you will find a very steep learning curve diving straight into Rails. There are some good free resources on the internet for learning Ruby, including:
|
26
26
|
|
27
27
|
* "Mr. Neighborly's Humble Little Ruby Book":http://www.humblelittlerubybook.com
|
28
28
|
* "Programming Ruby":http://www.ruby-doc.org/docs/ProgrammingRuby/
|
@@ -78,7 +78,7 @@ Rails ships as many individual components.
|
|
78
78
|
|
79
79
|
h5. Action Pack
|
80
80
|
|
81
|
-
Action Pack is a single gem that contains Action Controller, Action View and Action Dispatch.
|
81
|
+
Action Pack is a single gem that contains Action Controller, Action View and Action Dispatch. The "VC" part of "MVC".
|
82
82
|
|
83
83
|
h5. Action Controller
|
84
84
|
|
@@ -98,7 +98,7 @@ Action Mailer is a framework for building e-mail services. You can use Action Ma
|
|
98
98
|
|
99
99
|
h5. Active Model
|
100
100
|
|
101
|
-
Active Model provides a defined interface between the Action Pack gem services and Object Relationship Mapping gems such as Active Record.
|
101
|
+
Active Model provides a defined interface between the Action Pack gem services and Object Relationship Mapping gems such as Active Record. Active Model allows Rails to utilize other ORM frameworks in place of Active Record if your application needs this.
|
102
102
|
|
103
103
|
h5. Active Record
|
104
104
|
|
@@ -110,7 +110,7 @@ Active Resource provides a framework for managing the connection between busines
|
|
110
110
|
|
111
111
|
h5. Active Support
|
112
112
|
|
113
|
-
Active Support is an extensive collection of utility classes and standard Ruby library extensions that are used in
|
113
|
+
Active Support is an extensive collection of utility classes and standard Ruby library extensions that are used in Rails, both by the core code and by your applications.
|
114
114
|
|
115
115
|
h5. Railties
|
116
116
|
|
@@ -149,11 +149,11 @@ Usually run this as the root user:
|
|
149
149
|
# gem install rails
|
150
150
|
</shell>
|
151
151
|
|
152
|
-
TIP. If you're working on Windows, you
|
152
|
+
TIP. If you're working on Windows, you can quickly install Ruby and Rails with "Rails Installer":http://railsinstaller.org.
|
153
153
|
|
154
154
|
h4. Creating the Blog Application
|
155
155
|
|
156
|
-
The best way to use this guide is to follow each step as it happens, no code or step needed to make this example application has been left out, so you can literally follow along step by step.
|
156
|
+
The best way to use this guide is to follow each step as it happens, no code or step needed to make this example application has been left out, so you can literally follow along step by step. If you need to see the completed code, you can download it from "Getting Started Code":https://github.com/mikel/getting-started-code.
|
157
157
|
|
158
158
|
To begin, open a terminal, navigate to a folder where you have rights to create files, and type:
|
159
159
|
|
@@ -163,7 +163,7 @@ $ rails new blog
|
|
163
163
|
|
164
164
|
This will create a Rails application called Blog in a directory called blog.
|
165
165
|
|
166
|
-
TIP: You can see all of the switches that the Rails application builder accepts by running <tt>rails -h</tt>.
|
166
|
+
TIP: You can see all of the switches that the Rails application builder accepts by running <tt>rails new -h</tt>.
|
167
167
|
|
168
168
|
After you create the blog application, switch to its folder to continue work directly in that application:
|
169
169
|
|
@@ -184,7 +184,7 @@ In any case, Rails will create a folder in your working directory called <tt>blo
|
|
184
184
|
|doc/|In-depth documentation for your application.|
|
185
185
|
|lib/|Extended modules for your application (not covered in this guide).|
|
186
186
|
|log/|Application log files.|
|
187
|
-
|public/|The only folder seen to the world as-is.
|
187
|
+
|public/|The only folder seen to the world as-is. This is where your images, JavaScript files, stylesheets (CSS), and other static files go.|
|
188
188
|
|script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|
189
189
|
|test/|Unit tests, fixtures, and other test apparatus. These are covered in "Testing Rails Applications":testing.html|
|
190
190
|
|tmp/|Temporary files|
|
@@ -192,10 +192,10 @@ In any case, Rails will create a folder in your working directory called <tt>blo
|
|
192
192
|
|
193
193
|
h4. Installing the Required Gems
|
194
194
|
|
195
|
-
Rails applications manage gem dependencies with "Bundler":http://
|
195
|
+
Rails applications manage gem dependencies with "Bundler":http://gembundler.com/v1.0/index.html by default. As we don't need any other gems beyond the ones in the generated +Gemfile+ we can directly run
|
196
196
|
|
197
197
|
<shell>
|
198
|
-
bundle install
|
198
|
+
$ bundle install
|
199
199
|
</shell>
|
200
200
|
|
201
201
|
to have them ready.
|
@@ -227,7 +227,7 @@ NOTE: In this guide we are using an SQLite3 database for data storage, because i
|
|
227
227
|
|
228
228
|
h5. Configuring a MySQL Database
|
229
229
|
|
230
|
-
If you choose to use MySQL instead of the shipped
|
230
|
+
If you choose to use MySQL instead of the shipped SQLite3 database, your +config/database.yml+ will look a little different. Here's the development section:
|
231
231
|
|
232
232
|
<yaml>
|
233
233
|
development:
|
@@ -258,6 +258,8 @@ development:
|
|
258
258
|
|
259
259
|
Change the username and password in the +development+ section as appropriate.
|
260
260
|
|
261
|
+
TIP: You don't have to update the database configurations manually. If you had a look at the options of application generator, you have seen that one of them is named <tt>--database</tt>. It lets you choose an adapter for couple of most used relational databases. You can even run the generator repeatedly: <tt>cd .. && rails new blog --database=mysql</tt>. When you confirm the overwriting of the +config/database.yml+ file, your application will be configured for MySQL instead of SQLite.
|
262
|
+
|
261
263
|
h4. Creating the Database
|
262
264
|
|
263
265
|
Now that you have your database configured, it's time to have Rails create an empty database for you. You can do this by running a rake command:
|
@@ -272,7 +274,7 @@ TIP: Rake is a general-purpose command-runner that Rails uses for many things. Y
|
|
272
274
|
|
273
275
|
h3. Hello, Rails!
|
274
276
|
|
275
|
-
One of the traditional places to start with a new language is by getting some text up on screen quickly
|
277
|
+
One of the traditional places to start with a new language is by getting some text up on screen quickly. To do this, you need to get your Rails application server running.
|
276
278
|
|
277
279
|
h4. Starting up the Web Server
|
278
280
|
|
@@ -282,13 +284,13 @@ You actually have a functional Rails application already. To see it, you need to
|
|
282
284
|
$ rails server
|
283
285
|
</shell>
|
284
286
|
|
285
|
-
This will fire up an instance of the
|
287
|
+
This will fire up an instance of the WEBrick web server by default (Rails can also use several other web servers). To see your application in action, open a browser window and navigate to "http://localhost:3000":http://localhost:3000. You should see Rails' default information page:
|
286
288
|
|
287
289
|
!images/rails_welcome.png(Welcome Aboard screenshot)!
|
288
290
|
|
289
291
|
TIP: To stop the web server, hit Ctrl+C in the terminal window where it's running. In development mode, Rails does not generally require you to stop the server; changes you make in files will be automatically picked up by the server.
|
290
292
|
|
291
|
-
The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page.
|
293
|
+
The "Welcome Aboard" page is the _smoke test_ for a new Rails application: it makes sure that you have your software configured correctly enough to serve a page. You can also click on the _About your application’s environment_ link to see a summary of your Application's environment.
|
292
294
|
|
293
295
|
h4. Say "Hello", Rails
|
294
296
|
|
@@ -298,7 +300,7 @@ To get Rails saying "Hello", you need to create at minimum a controller and a vi
|
|
298
300
|
$ rails generate controller home index
|
299
301
|
</shell>
|
300
302
|
|
301
|
-
TIP: If you're on Windows, or your Ruby is set up in some non-standard fashion, you may need to explicitly pass Rails +rails+ commands to Ruby:
|
303
|
+
TIP: If you're on Windows, or your Ruby is set up in some non-standard fashion, you may need to explicitly pass Rails +rails+ commands to Ruby: <tt>ruby \path\to\your\application\script\rails generate controller home index</tt>.
|
302
304
|
|
303
305
|
Rails will create several files for you, including +app/views/home/index.html.erb+. This is the template that will be used to display the results of the +index+ action (method) in the +home+ controller. Open this file in your text editor and edit it to contain a single line of code:
|
304
306
|
|
@@ -308,7 +310,7 @@ Rails will create several files for you, including +app/views/home/index.html.er
|
|
308
310
|
|
309
311
|
h4. Setting the Application Home Page
|
310
312
|
|
311
|
-
Now that we have made the controller and view, we need to tell Rails when we want "Hello Rails" to show up.
|
313
|
+
Now that we have made the controller and view, we need to tell Rails when we want "Hello Rails" to show up. In our case, we want it to show up when we navigate to the root URL of our site, "http://localhost:3000":http://localhost:3000, instead of the "Welcome Aboard" smoke test.
|
312
314
|
|
313
315
|
The first step to doing this is to delete the default page from your application:
|
314
316
|
|
@@ -316,9 +318,9 @@ The first step to doing this is to delete the default page from your application
|
|
316
318
|
$ rm public/index.html
|
317
319
|
</shell>
|
318
320
|
|
319
|
-
We need to do this as Rails will deliver any static file in the +public+ directory in preference to any dynamic
|
321
|
+
We need to do this as Rails will deliver any static file in the +public+ directory in preference to any dynamic content we generate from the controllers.
|
320
322
|
|
321
|
-
Now, you have to tell Rails where your actual home page is located. Open the file +config/routes.rb+ in your editor. This is your application's _routing file_ which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. This file contains many sample routes on commented lines, and one of them actually shows you how to connect the root of your site to a specific controller and action. Find the line beginning with
|
323
|
+
Now, you have to tell Rails where your actual home page is located. Open the file +config/routes.rb+ in your editor. This is your application's _routing file_ which holds entries in a special DSL (domain-specific language) that tells Rails how to connect incoming requests to controllers and actions. This file contains many sample routes on commented lines, and one of them actually shows you how to connect the root of your site to a specific controller and action. Find the line beginning with +root :to+, uncomment it and change it like the following:
|
322
324
|
|
323
325
|
<ruby>
|
324
326
|
Blog::Application.routes.draw do
|
@@ -347,12 +349,12 @@ In the case of the blog application, you can start by generating a scaffolded Po
|
|
347
349
|
$ rails generate scaffold Post name:string title:string content:text
|
348
350
|
</shell>
|
349
351
|
|
350
|
-
NOTE. While scaffolding will get you up and running quickly, the
|
352
|
+
NOTE. While scaffolding will get you up and running quickly, the code it generates is unlikely to be a perfect fit for your application. You'll most probably want to customize the generated code. Many experienced Rails developers avoid scaffolding entirely, preferring to write all or most of their source code from scratch. Rails, however, makes it really simple to customize templates for generated models, controllers, views and other source files. You'll find more information in the "Creating and Customizing Rails Generators & Templates":generators.html guide.
|
351
353
|
|
352
354
|
The scaffold generator will build 15 files in your application, along with some folders, and edit one more. Here's a quick overview of what it creates:
|
353
355
|
|
354
356
|
|_.File |_.Purpose|
|
355
|
-
|db/migrate/20100207214725_create_posts.rb
|
357
|
+
|db/migrate/20100207214725_create_posts.rb |Migration to create the posts table in your database (your name will include a different timestamp)|
|
356
358
|
|app/models/post.rb |The Post model|
|
357
359
|
|test/fixtures/posts.yml |Dummy posts for use in testing|
|
358
360
|
|app/controllers/posts_controller.rb |The Posts controller|
|
@@ -366,7 +368,7 @@ The scaffold generator will build 15 files in your application, along with some
|
|
366
368
|
|test/functional/posts_controller_test.rb |Functional testing harness for the posts controller|
|
367
369
|
|test/unit/helpers/posts_helper_test.rb |Unit testing harness for the posts helper|
|
368
370
|
|config/routes.rb |Edited to include routing information for posts|
|
369
|
-
|
|
371
|
+
|app/assets/stylesheets/scaffold.css.scss |Cascading style sheet to make the scaffolded views look better|
|
370
372
|
|
371
373
|
h4. Running a Migration
|
372
374
|
|
@@ -376,7 +378,7 @@ If you look in the +db/migrate/20100207214725_create_posts.rb+ file (remember, y
|
|
376
378
|
|
377
379
|
<ruby>
|
378
380
|
class CreatePosts < ActiveRecord::Migration
|
379
|
-
def
|
381
|
+
def change
|
380
382
|
create_table :posts do |t|
|
381
383
|
t.string :name
|
382
384
|
t.string :title
|
@@ -385,14 +387,10 @@ class CreatePosts < ActiveRecord::Migration
|
|
385
387
|
t.timestamps
|
386
388
|
end
|
387
389
|
end
|
388
|
-
|
389
|
-
def self.down
|
390
|
-
drop_table :posts
|
391
|
-
end
|
392
390
|
end
|
393
391
|
</ruby>
|
394
392
|
|
395
|
-
The above migration creates
|
393
|
+
The above migration creates a method name +change+ which will be called when you run this migration. The action defined in that method is also reversible, which means Rails knows how to reverse the change made by this migration, in case you want to reverse it at later date. By default, when you run this migration it will creates a +posts+ table with two string columns and a text column. It also creates two timestamp fields to track record creation and updating. More information about Rails migrations can be found in the "Rails Database Migrations":migrations.html guide.
|
396
394
|
|
397
395
|
At this point, you can use a rake command to run the migration:
|
398
396
|
|
@@ -409,7 +407,7 @@ Rails will execute this migration command and tell you it created the Posts tabl
|
|
409
407
|
== CreatePosts: migrated (0.0020s) ===========================================
|
410
408
|
</shell>
|
411
409
|
|
412
|
-
NOTE. Because you're working in the development environment by default, this command will apply to the database defined in the +development+ section of your +config/database.yml+ file.
|
410
|
+
NOTE. Because you're working in the development environment by default, this command will apply to the database defined in the +development+ section of your +config/database.yml+ file. If you would like to execute migrations in other environment, for instance in production, you must explicitly pass it when invoking the command: <tt>rake db:migrate RAILS_ENV=production</tt>.
|
413
411
|
|
414
412
|
h4. Adding a Link
|
415
413
|
|
@@ -467,6 +465,8 @@ To see your validations in action, you can use the console. The console is a com
|
|
467
465
|
$ rails console
|
468
466
|
</shell>
|
469
467
|
|
468
|
+
TIP: The default console will make changes to your database. You can instead open a console that will roll back any changes you make by using +rails console --sandbox+.
|
469
|
+
|
470
470
|
After the console loads, you can use it to work with your application's models:
|
471
471
|
|
472
472
|
<shell>
|
@@ -490,24 +490,24 @@ TIP: Unlike the development web server, the console does not automatically load
|
|
490
490
|
|
491
491
|
h4. Listing All Posts
|
492
492
|
|
493
|
-
The easiest place to start looking at functionality is with the code that lists all posts. Open the file +app/controllers/posts_controller.rb
|
493
|
+
The easiest place to start looking at functionality is with the code that lists all posts. Open the file +app/controllers/posts_controller.rb+ and look at the +index+ action:
|
494
494
|
|
495
495
|
<ruby>
|
496
496
|
def index
|
497
497
|
@posts = Post.all
|
498
498
|
|
499
499
|
respond_to do |format|
|
500
|
-
format.html
|
501
|
-
format.
|
500
|
+
format.html # index.html.erb
|
501
|
+
format.json { render :json => @posts }
|
502
502
|
end
|
503
503
|
end
|
504
504
|
</ruby>
|
505
505
|
|
506
|
-
+Post.all+ calls the +Post+ model to return all of the posts currently in the database. The result of this call is an array
|
506
|
+
+Post.all+ calls the +Post+ model to return all of the posts currently in the database. The result of this call is an array of posts that we store in a instance variable called +@posts+.
|
507
507
|
|
508
508
|
TIP: For more information on finding records with Active Record, see "Active Record Query Interface":active_record_querying.html.
|
509
509
|
|
510
|
-
The +respond_to+ block handles both HTML and
|
510
|
+
The +respond_to+ block handles both HTML and JSON calls to this action. If you browse to "http://localhost:3000/posts.json":http://localhost:3000/posts.json, you'll see a JSON containing all of the posts. The HTML format looks for a view in +app/views/posts/+ with a name that corresponds to the action name. Rails makes all of the instance variables from the action available to the view. Here's +app/views/posts/index.html.erb+:
|
511
511
|
|
512
512
|
<erb>
|
513
513
|
<h1>Listing posts</h1>
|
@@ -544,13 +544,13 @@ This view iterates over the contents of the +@posts+ array to display content an
|
|
544
544
|
* +link_to+ builds a hyperlink to a particular destination
|
545
545
|
* +edit_post_path+ and +new_post_path+ are helpers that Rails provides as part of RESTful routing. You'll see a variety of these helpers for the different actions that the controller includes.
|
546
546
|
|
547
|
-
NOTE. In previous versions of Rails, you had to use +<%=h post.name %>+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default.
|
547
|
+
NOTE. In previous versions of Rails, you had to use +<%=h post.name %>+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use +<%= raw post.name %>+.
|
548
548
|
|
549
549
|
TIP: For more details on the rendering process, see "Layouts and Rendering in Rails":layouts_and_rendering.html.
|
550
550
|
|
551
551
|
h4. Customizing the Layout
|
552
552
|
|
553
|
-
The view is only part of the story of how HTML is displayed in your web browser. Rails also has the concept of +layouts+, which are containers for views. When Rails renders a view to the browser, it does so by putting the view's HTML into a layout's HTML. In previous versions of Rails, the +rails generate scaffold+ command would automatically create a controller specific layout, like +app/views/layouts/posts.html.erb+, for the posts controller. However this has been changed in Rails 3.0.
|
553
|
+
The view is only part of the story of how HTML is displayed in your web browser. Rails also has the concept of +layouts+, which are containers for views. When Rails renders a view to the browser, it does so by putting the view's HTML into a layout's HTML. In previous versions of Rails, the +rails generate scaffold+ command would automatically create a controller specific layout, like +app/views/layouts/posts.html.erb+, for the posts controller. However this has been changed in Rails 3.0. An application specific +layout+ is used for all the controllers and can be found in +app/views/layouts/application.html.erb+. Open this layout in your editor and modify the +body+ tag:
|
554
554
|
|
555
555
|
<erb>
|
556
556
|
<!DOCTYPE html>
|
@@ -559,7 +559,7 @@ The view is only part of the story of how HTML is displayed in your web browser.
|
|
559
559
|
<title>Blog</title>
|
560
560
|
<%= stylesheet_link_tag :all %>
|
561
561
|
<%= javascript_include_tag :defaults %>
|
562
|
-
<%=
|
562
|
+
<%= csrf_meta_tags %>
|
563
563
|
</head>
|
564
564
|
<body style="background: #EEEEEE;">
|
565
565
|
|
@@ -580,8 +580,8 @@ def new
|
|
580
580
|
@post = Post.new
|
581
581
|
|
582
582
|
respond_to do |format|
|
583
|
-
format.html
|
584
|
-
format.
|
583
|
+
format.html # new.html.erb
|
584
|
+
format.json { render :json => @post }
|
585
585
|
end
|
586
586
|
end
|
587
587
|
</ruby>
|
@@ -596,7 +596,7 @@ The +new.html.erb+ view displays this empty Post to the user:
|
|
596
596
|
<%= link_to 'Back', posts_path %>
|
597
597
|
</erb>
|
598
598
|
|
599
|
-
The +<%= render 'form' %>+ line is our first introduction to _partials_ in Rails.
|
599
|
+
The +<%= render 'form' %>+ line is our first introduction to _partials_ in Rails. A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
|
600
600
|
|
601
601
|
If you take a look at +views/posts/_form.html.erb+ file, you will see the following:
|
602
602
|
|
@@ -649,13 +649,13 @@ def create
|
|
649
649
|
|
650
650
|
respond_to do |format|
|
651
651
|
if @post.save
|
652
|
-
format.html
|
652
|
+
format.html { redirect_to(@post,
|
653
653
|
:notice => 'Post was successfully created.') }
|
654
|
-
format.
|
654
|
+
format.json { render :json => @post,
|
655
655
|
:status => :created, :location => @post }
|
656
656
|
else
|
657
|
-
format.html
|
658
|
-
format.
|
657
|
+
format.html { render :action => "new" }
|
658
|
+
format.json { render :json => @post.errors,
|
659
659
|
:status => :unprocessable_entity }
|
660
660
|
end
|
661
661
|
end
|
@@ -666,7 +666,7 @@ The +create+ action instantiates a new Post object from the data supplied by the
|
|
666
666
|
|
667
667
|
If the post was not successfully saved, due to a validation error, then the controller returns the user back to the +new+ action with any error messages so that the user has the chance to fix the error and try again.
|
668
668
|
|
669
|
-
The "Post was successfully created" message is stored inside of the Rails +flash+ hash, (usually just called
|
669
|
+
The "Post was successfully created." message is stored inside of the Rails +flash+ hash, (usually just called _the flash_) so that messages can be carried over to another action, providing the user with useful information on the status of their request. In the case of +create+, the user never actually sees any page rendered during the Post creation process, because it immediately redirects to the new Post as soon Rails saves the record. The Flash carries over a message to the next action, so that when the user is redirected back to the +show+ action, they are presented with a message saying "Post was successfully created."
|
670
670
|
|
671
671
|
h4. Showing an Individual Post
|
672
672
|
|
@@ -677,8 +677,8 @@ def show
|
|
677
677
|
@post = Post.find(params[:id])
|
678
678
|
|
679
679
|
respond_to do |format|
|
680
|
-
format.html
|
681
|
-
format.
|
680
|
+
format.html # show.html.erb
|
681
|
+
format.json { render :json => @post }
|
682
682
|
end
|
683
683
|
end
|
684
684
|
</ruby>
|
@@ -739,12 +739,12 @@ def update
|
|
739
739
|
|
740
740
|
respond_to do |format|
|
741
741
|
if @post.update_attributes(params[:post])
|
742
|
-
format.html
|
742
|
+
format.html { redirect_to(@post,
|
743
743
|
:notice => 'Post was successfully updated.') }
|
744
|
-
format.
|
744
|
+
format.json { render :json => {}, :status => :ok }
|
745
745
|
else
|
746
|
-
format.html
|
747
|
-
format.
|
746
|
+
format.html { render :action => "edit" }
|
747
|
+
format.json { render :json => @post.errors,
|
748
748
|
:status => :unprocessable_entity }
|
749
749
|
end
|
750
750
|
end
|
@@ -763,8 +763,8 @@ def destroy
|
|
763
763
|
@post.destroy
|
764
764
|
|
765
765
|
respond_to do |format|
|
766
|
-
format.html
|
767
|
-
format.
|
766
|
+
format.html { redirect_to(posts_url) }
|
767
|
+
format.json { render :json => {}, :status => :ok }
|
768
768
|
end
|
769
769
|
end
|
770
770
|
</ruby>
|
@@ -803,7 +803,7 @@ In addition to the model, Rails has also made a migration to create the correspo
|
|
803
803
|
|
804
804
|
<ruby>
|
805
805
|
class CreateComments < ActiveRecord::Migration
|
806
|
-
def
|
806
|
+
def change
|
807
807
|
create_table :comments do |t|
|
808
808
|
t.string :commenter
|
809
809
|
t.text :body
|
@@ -811,15 +811,13 @@ class CreateComments < ActiveRecord::Migration
|
|
811
811
|
|
812
812
|
t.timestamps
|
813
813
|
end
|
814
|
-
end
|
815
814
|
|
816
|
-
|
817
|
-
drop_table :comments
|
815
|
+
add_index :comments, :post_id
|
818
816
|
end
|
819
817
|
end
|
820
818
|
</ruby>
|
821
819
|
|
822
|
-
The +t.references+ line sets up a foreign key column for the association between the two models. Go ahead and run the migration:
|
820
|
+
The +t.references+ line sets up a foreign key column for the association between the two models. And the +add_index+ line sets up an index for this association column. Go ahead and run the migration:
|
823
821
|
|
824
822
|
<shell>
|
825
823
|
$ rake db:migrate
|
@@ -867,7 +865,7 @@ TIP: For more information on Active Record associations, see the "Active Record
|
|
867
865
|
|
868
866
|
h4. Adding a Route for Comments
|
869
867
|
|
870
|
-
As with the +home+ controller, we will need to add a route so that Rails knows where we would like to navigate to see +comments+.
|
868
|
+
As with the +home+ controller, we will need to add a route so that Rails knows where we would like to navigate to see +comments+. Open up the +config/routes.rb+ file again, you will see an entry that was added automatically for +posts+ near the top by the scaffold generator, +resources :posts+, edit it as follows:
|
871
869
|
|
872
870
|
<ruby>
|
873
871
|
resources :posts do
|
@@ -895,7 +893,7 @@ This creates four files and one empty directory:
|
|
895
893
|
* +test/unit/helpers/comments_helper_test.rb+ - The unit tests for the helper
|
896
894
|
* +app/views/comments/+ - Views of the controller are stored here
|
897
895
|
|
898
|
-
Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed.
|
896
|
+
Like with any blog, our readers will create their comments directly after reading the post, and once they have added their comment, will be sent back to the post show page to see their comment now listed. Due to this, our +CommentsController+ is there to provide a method to create comments and delete SPAM comments when they arrive.
|
899
897
|
|
900
898
|
So first, we'll wire up the Post show template (+/app/views/posts/show.html.erb+) to let us make a new comment:
|
901
899
|
|
@@ -1049,8 +1047,7 @@ Then in the +app/views/posts/show.html.erb+ you can change it to look like the f
|
|
1049
1047
|
</p>
|
1050
1048
|
|
1051
1049
|
<h2>Comments</h2>
|
1052
|
-
<%= render
|
1053
|
-
:collection => @post.comments %>
|
1050
|
+
<%= render @post.comments %>
|
1054
1051
|
|
1055
1052
|
<h2>Add a comment:</h2>
|
1056
1053
|
<%= form_for([@post, @post.comments.build]) do |f| %>
|
@@ -1073,7 +1070,7 @@ Then in the +app/views/posts/show.html.erb+ you can change it to look like the f
|
|
1073
1070
|
<%= link_to 'Back to Posts', posts_path %> |
|
1074
1071
|
</erb>
|
1075
1072
|
|
1076
|
-
This will now render the partial in +app/views/comments/_comment.html.erb+ once for each comment that is in the +@post.comments+ collection.
|
1073
|
+
This will now render the partial in +app/views/comments/_comment.html.erb+ once for each comment that is in the +@post.comments+ collection. As the +render+ method iterates over the <tt>@post.comments</tt> collection, it assigns each comment to a local variable named the same as the partial, in this case +comment+ which is then available in the partial for us to show.
|
1077
1074
|
|
1078
1075
|
h4. Rendering a Partial Form
|
1079
1076
|
|
@@ -1116,8 +1113,7 @@ Then you make the +app/views/posts/show.html.erb+ look like the following:
|
|
1116
1113
|
</p>
|
1117
1114
|
|
1118
1115
|
<h2>Comments</h2>
|
1119
|
-
<%= render
|
1120
|
-
:collection => @post.comments %>
|
1116
|
+
<%= render @post.comments %>
|
1121
1117
|
|
1122
1118
|
<h2>Add a comment:</h2>
|
1123
1119
|
<%= render "comments/form" %>
|
@@ -1134,7 +1130,7 @@ The +@post+ object is available to any partials rendered in the view because we
|
|
1134
1130
|
|
1135
1131
|
h3. Deleting Comments
|
1136
1132
|
|
1137
|
-
Another important feature on a blog is being able to delete SPAM comments.
|
1133
|
+
Another important feature on a blog is being able to delete SPAM comments. To do this, we need to implement a link of some sort in the view and a +DELETE+ action in the +CommentsController+.
|
1138
1134
|
|
1139
1135
|
So first, let's add the delete link in the +app/views/comments/_comment.html.erb+ partial:
|
1140
1136
|
|
@@ -1197,36 +1193,19 @@ h3. Security
|
|
1197
1193
|
|
1198
1194
|
If you were to publish your blog online, anybody would be able to add, edit and delete posts or delete comments.
|
1199
1195
|
|
1200
|
-
Rails provides a very simple HTTP authentication system that will work nicely in this situation.
|
1201
|
-
|
1202
|
-
<ruby>
|
1203
|
-
class ApplicationController < ActionController::Base
|
1204
|
-
protect_from_forgery
|
1205
|
-
|
1206
|
-
private
|
1207
|
-
|
1208
|
-
def authenticate
|
1209
|
-
authenticate_or_request_with_http_basic do |user_name, password|
|
1210
|
-
user_name == 'admin' && password == 'password'
|
1211
|
-
end
|
1212
|
-
end
|
1213
|
-
|
1214
|
-
end
|
1215
|
-
</ruby>
|
1216
|
-
|
1217
|
-
You can obviously change the username and password to whatever you want. We put this method inside of +ApplicationController+ so that it is available to all of our controllers.
|
1196
|
+
Rails provides a very simple HTTP authentication system that will work nicely in this situation.
|
1218
1197
|
|
1219
|
-
|
1198
|
+
In the +PostsController+ we need to have a way to block access to the various actions if the person is not authenticated, here we can use the Rails <tt>http_basic_authenticate_with</tt> method, allowing access to the requested action if that method allows it.
|
1220
1199
|
|
1221
|
-
To use the
|
1200
|
+
To use the authentication system, we specify it at the top of our +PostsController+, in this case, we want the user to be authenticated on every action, except for +index+ and +show+, so we write that:
|
1222
1201
|
|
1223
1202
|
<ruby>
|
1224
1203
|
class PostsController < ApplicationController
|
1225
1204
|
|
1226
|
-
|
1205
|
+
http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index
|
1227
1206
|
|
1228
1207
|
# GET /posts
|
1229
|
-
# GET /posts.
|
1208
|
+
# GET /posts.json
|
1230
1209
|
def index
|
1231
1210
|
@posts = Post.all
|
1232
1211
|
respond_to do |format|
|
@@ -1238,7 +1217,7 @@ We also only want to allow authenticated users to delete comments, so in the +Co
|
|
1238
1217
|
<ruby>
|
1239
1218
|
class CommentsController < ApplicationController
|
1240
1219
|
|
1241
|
-
|
1220
|
+
http_basic_authenticate_with :name => "dhh", :password => "secret", :only => :destroy
|
1242
1221
|
|
1243
1222
|
def create
|
1244
1223
|
@post = Post.find(params[:post_id])
|
@@ -1325,7 +1304,7 @@ Note that we have changed the +f+ in +form_for(@post) do |f|+ to +post_form+ to
|
|
1325
1304
|
|
1326
1305
|
This example shows another option of the render helper, being able to pass in local variables, in this case, we want the local variable +form+ in the partial to refer to the +post_form+ object.
|
1327
1306
|
|
1328
|
-
We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make sure there is a new tag ready to have it's name filled in by the user.
|
1307
|
+
We also add a <tt>@post.tags.build</tt> at the top of this form, this is to make sure there is a new tag ready to have it's name filled in by the user. If you do not build the new tag, then the form will not appear as there is no new Tag object ready to create.
|
1329
1308
|
|
1330
1309
|
Now create the folder <tt>app/views/tags</tt> and make a file in there called <tt>_form.html.erb</tt> which contains the form for the tag:
|
1331
1310
|
|
@@ -1370,8 +1349,7 @@ Finally, we will edit the <tt>app/views/posts/show.html.erb</tt> template to sho
|
|
1370
1349
|
</p>
|
1371
1350
|
|
1372
1351
|
<h2>Comments</h2>
|
1373
|
-
<%= render
|
1374
|
-
:collection => @post.comments %>
|
1352
|
+
<%= render @post.comments %>
|
1375
1353
|
|
1376
1354
|
<h2>Add a comment:</h2>
|
1377
1355
|
<%= render "comments/form" %>
|
@@ -1387,7 +1365,7 @@ However, that method call <tt>@post.tags.map { |t| t.name }.join(", ")</tt> is a
|
|
1387
1365
|
|
1388
1366
|
h3. View Helpers
|
1389
1367
|
|
1390
|
-
View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable code for views.
|
1368
|
+
View Helpers live in <tt>app/helpers</tt> and provide small snippets of reusable code for views. In our case, we want a method that strings a bunch of objects together using their name attribute and joining them with a comma. As this is for the Post show template, we put it in the PostsHelper.
|
1391
1369
|
|
1392
1370
|
Open up <tt>app/helpers/posts_helper.rb</tt> and add the following:
|
1393
1371
|
|
@@ -1425,8 +1403,7 @@ Now you can edit the view in <tt>app/views/posts/show.html.erb</tt> to look like
|
|
1425
1403
|
</p>
|
1426
1404
|
|
1427
1405
|
<h2>Comments</h2>
|
1428
|
-
<%= render
|
1429
|
-
:collection => @post.comments %>
|
1406
|
+
<%= render @post.comments %>
|
1430
1407
|
|
1431
1408
|
<h2>Add a comment:</h2>
|
1432
1409
|
<%= render "comments/form" %>
|
@@ -1473,6 +1450,8 @@ Two very common sources of data that are not UTF-8:
|
|
1473
1450
|
|
1474
1451
|
h3. Changelog
|
1475
1452
|
|
1453
|
+
* April 26, 2011: Changed migration code from +up+, +down+ pair to +change+ method "Prem Sichanugrist":"http://sikachu.com"
|
1454
|
+
* April 11, 2011: Changed scaffold_controller generator to create format block for JSON instead of XML "Sebastian Martinez":http://www.wyeworks.com
|
1476
1455
|
* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl
|
1477
1456
|
* July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com
|
1478
1457
|
* May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com
|