@@ -52,7 +52,7 @@ NOTE: This output will seem very familiar when we get to the `generate` command.
=== server ===
Let's try it! The `server` command launches a small web server written in Ruby named WEBrick which was also installed when you installed Rails. You'll use this any time you want to view your work through a web browser.
Let's try it! The `server` command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to view your work through a web browser.
NOTE: WEBrick isn't your only option for serving Rails. We'll get to that in a later section. [XXX: which section]
...
...
@@ -99,7 +99,7 @@ Using generators will save you a large amount of time by writing *boilerplate co
Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator:
NOTE: All Rails console utilities have help text. For commands that require a lot of input to run correctly, you can try the command without any parameters (like `rails` or `./script/generate`). For others, you can try adding `--help` or `-h` to the end, as in `./script/server --help`.
NOTE: All Rails console utilities have help text. As with most *NIX utilities, you can try adding `--help` or `-h` to the end, for example `./script/server --help`.
Let's set up a simple model called "HighScore" that will keep track of our highest score on video games we play. Then we'll wire up our controller and view to modify and list our scores.
But instead of generating a model directly (which we'll be doing later), let's set up a scaffold. A *scaffold* in Rails is a full set of model, database migration for that model, controller to manipulate it, views to view and manipulate the data, and a test suite for each of the above.
Let's set up a simple resource called "HighScore" that will keep track of our highest score on video games we play.
Taking it from the top, we have the *models* directory, where all of your data models live. *test/unit*, where all the unit tests live (gasp! -- unit tests!), fixtures for those tests, a test, the *migrate* directory, where the database-modifying migrations live, and a migration to create the `high_scores` table with the right fields.
Taking it from the top - the generator checks that there exist the directories for models, controllers, helpers, layouts, functional and unit tests, stylesheets, creates the views, controller, model and database migration for HighScore (creating the `high_scores` table and fields), takes care of the route for the *resource*, and new tests for everything.
The migration requires that we *migrate*, that is, run some Ruby code (living in that `20081217071914_create_high_scores.rb`) to modify the schema of our database. Which database? The sqlite3 database that Rails will create for you when we run the `rake db:migrate` command. We'll talk more about Rake in-depth in a little while.
The migration requires that we *migrate*, that is, run some Ruby code (living in that `20081126032945_create_high_scores.rb`) to modify the schema of our database. Which database? The sqlite3 database that Rails will create for you when we run the `rake db:migrate` command. We'll talk more about Rake in-depth in a little while.
NOTE: Hey. Install the sqlite3-ruby gem while you're at it. `gem install sqlite3-ruby`
NOTE: Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment.
Yo! Let's shove a small table into our greeting controller and view, listing our sweet scores.
Let's see the interface Rails created for us. ./script/server; http://localhost:3000/high_scores
[source,ruby]
We can create new high scores (55,160 on Space Invaders!)
=== console ===
The `console` command lets you interact with your Rails application from the command line. On the underside, `script/console` uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.
=== dbconsole ===
`dbconsole` figures out which database you're using and drops you into whichever command line interface you would use with it (and figures out the command line parameters to give to it, too!). It supports MySQL, PostgreSQL, SQLite and SQLite3.
=== plugin ===
The `plugin` command simplifies plugin management; think a miniature version of the Gem utility. Let's walk through installing a plugin. You can call the sub-command *discover*, which sifts through repositories looking for plugins, or call *source* to add a specific repository of plugins, or you can specify the plugin location directly.
Let's say you're creating a website for a client who wants a small accounting system. Every event having to do with money must be logged, and must never be deleted. Wouldn't it be great if we could override the behavior of a model to never actually take its record out of the database, but *instead*, just set a field?
There is such a thing! The plugin we're installing is called "acts_as_paranoid", and it lets models implement a "deleted_at" column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things.
Think of `destroy` as the opposite of `generate`. It'll figure out what generate did, and undo it. Believe you-me, the creation of this tutorial used this command many times!
XXX: Go with scaffolding instead, modifying greeting controller for high scores seems dumb.
Check it: Version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version! `about` is useful when you need to ask help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.
@@ -247,7 +247,7 @@ A nice thing about `f.text_field` and other helper methods is that they will pre
Relying on record identification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the previous chapter we handled the Article model. This model is directly available to users of our application and, following the best practices for developing with Rails, we should declare it *a resource*.
In the previous chapter we handled the Article model. This model is directly available to users of our application, so -- following the best practices for developing with Rails -- we should declare it *a resource*.
When dealing with RESTful resources, our calls to `form_for` can get significantly easier if we rely on *record identification*. In short, we can just pass the model instance and have Rails figure out model name and the rest:
...
...
@@ -291,15 +291,13 @@ Here we have a list of cities where their names are presented to the user, but i
The select tag and options
~~~~~~~~~~~~~~~~~~~~~~~~~~
The most generic helper is `select_tag`, which -- as the name implies -- simply generates the `SELECT` tag that encapsulates the options:
The most generic helper is `select_tag`, which -- as the name implies -- simply generates the `SELECT` tag that encapsulates an options string:
So whenever Rails sees that the internal value of an option being generated matches this value, it will add the `selected` attribute to that option.
Select boxes for dealing with models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Select helpers for dealing with models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Until now we've covered how to make generic select boxes, but in most cases our form controls will be tied to a specific database model. So, to continue from our previous examples, let's assume that we have a "Person" model with a `city_id` attribute.
Consistent with other form helpers, when dealing with models we drop the `"_tag"` suffix from `select_tag` that we used in previous examples:
Notice that the third parameter, the options array, is the same kind of argument we pass to `options_for_select`. One thing that we have as an advantage here is that we don't have to worry about pre-selecting the correct city if the user already has one -- Rails will do this for us by reading from `@person.city_id` attribute.
As before, if we were to use `select` helper on a form builder scoped to `@person` object, the syntax would be:
But what if we had a *City* model (perhaps an ActiveRecord one) and we wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
This is a perfectly valid solution, but Rails provides us with a less verbose alternative: `options_from_collection_for_select`. This helper expects a collection of arbitrary objects and two additional arguments: the names of the methods to read the option *value* and *text* from, respectively:
To recap, `options_from_collection_for_select` are to `collection_select` what `options_for_select` are to `select`.
Time zone and country select
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To leverage time zone support in Rails, we have to ask our users what time zone they are in. Doing so would require generating select options from a list of pre-defined TimeZone objects using `collection_select`, but we can simply use the `time_zone_select` helper that already wraps this:
There is also `time_zone_options_for_select` helper for a more manual (therefore more customizable) way of doing this. Read the API documentation to learn about the possible arguments for these two methods.
When it comes to country select, Rails _used_ to have the built-in helper `country_select` but was extracted to a plugin.
TODO: plugin URL
Miscellaneous
-------------
File upload form
~~~~~~~~~~~~~~~~
:multipart - If set to true, the enctype is set to "multipart/form-data".
Scoping out form controls with `fields_for`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a scope around a specific model object like `form_for`, but doesn’t create the form tags themselves. This makes `fields_for` suitable for specifying additional model objects in the same form:
Making custom form builders
~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder. For example, let’s say you made a helper to automatically add labels to form inputs.