提交 62f865db 编写于 作者: M Michael Lavrisha

Merge branch 'master' of github.com:lifo/docrails

......@@ -287,7 +287,7 @@ def touch(name = nil)
private
# A hook to be overriden by association modules.
# A hook to be overridden by association modules.
def destroy_associations
end
......
......@@ -216,6 +216,8 @@ If you follow this guide, you'll create a Rails project called <tt>blog</tt>, a
(very) simple weblog. Before you can start building the application, you need to
make sure that you have Rails itself installed.
TIP: The examples below use # and $ to denote terminal prompts. If you are using Windows, your prompt will look something like c:\source_code>
h4. Installing Rails
In most cases, the easiest way to install Rails is to take advantage of RubyGems:
......@@ -246,7 +248,8 @@ $ rails new blog
This will create a Rails application called Blog in a directory called blog.
TIP: You can see all of the switches that the Rails application builder accepts
by running <tt>rails new -h</tt>.
by running
<tt>rails new -h</tt>.
After you create the blog application, switch to its folder to continue work
directly in that application:
......@@ -278,18 +281,6 @@ by default:
|tmp/|Temporary files|
|vendor/|A place for all third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality.|
h4. Installing the Required Gems
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
<shell>
$ bundle install
</shell>
to have them ready.
h4. Configuring a Database
Just about every Rails application will interact with a database. The database
......@@ -405,12 +396,12 @@ development:
Change the username and password in the +development+ section as appropriate.
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
TIP: You don't have to update the database configurations manually. If you look at the
options of the application generator, you will see that one of the options
is named <tt>--database</tt>. This option allows you to choose an adapter from a
list of the 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.
h4. Creating the Database
......@@ -470,8 +461,8 @@ your terminal:
$ rails generate controller home index
</shell>
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
TIP: If you get a command not found error when running this command, you
need to explicitly pass Rails +rails+ commands to Ruby: <tt>ruby
\path\to\your\application\script\rails generate controller home index</tt>.
Rails will create several files for you, including
......
......@@ -477,7 +477,7 @@ Several methods are provided that allow you to control all this:
For example, this migration
<ruby>
<pre>
class CreateProducts < ActiveRecord::Migration
def change
suppress_messages do
......@@ -496,7 +496,7 @@ class CreateProducts < ActiveRecord::Migration
end
end
end
</ruby>
</pre>
generates the following output
......@@ -514,40 +514,107 @@ If you just want Active Record to shut up then running +rake db:migrate VERBOSE=
h3. Using Models in Your Migrations
When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done but some caution should be observed.
When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done, but some caution should be observed.
Consider for example a migration that uses the +Product+ model to update a row in the corresponding table. Alice later updates the +Product+ model, adding a new column and a validation on it. Bob comes back from holiday, updates the source and runs outstanding migrations with +rake db:migrate+, including the one that used the +Product+ model. When the migration runs the source is up to date and so the +Product+ model has the validation added by Alice. The database however is still old and so does not have that column and an error ensues because that validation is on a column that does not yet exist.
For example, problems occur when the model uses database columns which are (1) not currently in the database and (2) will be created by this or a subsequent migration.
Frequently I just want to update rows in the database without writing out the SQL by hand: I'm not using anything specific to the model. One pattern for this is to define a copy of the model inside the migration itself, for example:
Consider this example, where Alice and Bob are working on the same code base which contains a +Product+ model:
<ruby>
class AddPartNumberToProducts < ActiveRecord::Migration
class Product < ActiveRecord::Base
Bob goes on vacation.
Alice creates a migration for the +products+ table which adds a new column and initializes it.
She also adds a validation to the Product model for the new column.
<pre>
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration
def change
add_column :products, :flag, :int
Product.all.each { |f| f.update_attributes!(:flag => 'false') }
end
end
</pre>
<pre>
# app/model/product.rb
class Product < ActiveRecord::Base
validates_presence_of :flag
end
</pre>
Alice adds a second migration which adds and initializes another column to the +products+ table and also adds a validation to the Product model for the new column.
<pre>
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration
def change
...
add_column :products, :fuzz, :string
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
</ruby>
The migration has its own minimal copy of the +Product+ model and no longer cares about the +Product+ model defined in the application.
</pre>
h4. Dealing with Changing Models
<pre>
# app/model/product.rb
For performance reasons information about the columns a model has is cached. For example if you add a column to a table and then try and use the corresponding model to insert a new row it may try to use the old column information. You can force Active Record to re-read the column information with the +reset_column_information+ method, for example
class Product < ActiveRecord::Base
validates_presence_of :flag
validates_presence_of :fuzz
end
</pre>
<ruby>
class AddPartNumberToProducts < ActiveRecord::Migration
Both migrations work for Alice.
Bob comes back from vacation and:
# updates the source - which contains both migrations and the latests version of the Product model.
# runs outstanding migrations with +rake db:migrate+, which includes the one that updates the +Product+ model.
The migration crashes because when the model attempts to save, it tries to validate the second added column, which is not in the database when the _first_ migration runs.
<pre>
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `fuzz' for #<Product:0x000001049b14a0>
</pre>
A fix for this is to create a local model within the migration. This keeps rails from running the validations, so that the migrations run to completion.
When using a faux model, it's a good idea to call +Product.reset_column_information+ to refresh the ActiveRecord cache for the Product model prior to updating data in the database.
If Alice had done this instead, there would have been no problem:
<pre>
# db/migrate/20100513121110_add_flag_to_product.rb
class AddFlagToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :flag, :int
Product.reset_column_information
Product.all.each { |f| f.update_attributes!(:flag => false) }
end
end
</pre>
<pre>
# db/migrate/20100515121110_add_fuzz_to_product.rb
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :product, :part_number, :string
add_column :products, :fuzz, :string
Product.reset_column_information
...
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
</ruby>
</pre>
h3. Schema Dumping and You
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册