aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
Diffstat (limited to 'guides')
-rw-r--r--guides/Rakefile6
-rw-r--r--guides/rails_guides/generator.rb6
-rw-r--r--guides/rails_guides/kindle.rb119
-rw-r--r--guides/source/4_0_release_notes.md42
-rw-r--r--guides/source/active_record_basics.md224
-rw-r--r--guides/source/association_basics.md130
-rw-r--r--guides/source/configuring.md2
-rw-r--r--guides/source/development_dependencies_install.md3
-rw-r--r--guides/source/documents.yaml4
-rw-r--r--guides/source/getting_started.md9
-rw-r--r--guides/source/index.html.erb4
-rw-r--r--guides/source/kindle/rails_guides.opf.erb2
12 files changed, 493 insertions, 58 deletions
diff --git a/guides/Rakefile b/guides/Rakefile
index 7881a3d9b3..d6dd950d01 100644
--- a/guides/Rakefile
+++ b/guides/Rakefile
@@ -13,6 +13,12 @@ namespace :guides do
desc "Generate .mobi file. The kindlegen executable must be in your PATH. You can get it for free from http://www.amazon.com/kindlepublishing"
task :kindle do
+ unless `kindlerb -v 2> /dev/null` =~ /kindlerb 0.1.1/
+ abort "Please `gem install kindlerb`"
+ end
+ unless `convert` =~ /convert/
+ abort "Please install ImageMagick`"
+ end
ENV['KINDLE'] = '1'
Rake::Task['guides:generate:html'].invoke
end
diff --git a/guides/rails_guides/generator.rb b/guides/rails_guides/generator.rb
index a53d34a279..af9c5b8372 100644
--- a/guides/rails_guides/generator.rb
+++ b/guides/rails_guides/generator.rb
@@ -112,11 +112,9 @@ module RailsGuides
end
def generate_mobi
- opf = "#{output_dir}/rails_guides.opf"
+ require 'rails_guides/kindle'
out = "#{output_dir}/kindlegen.out"
-
- system "kindlegen #{opf} -o #{mobi} > #{out} 2>&1"
- puts "Guides compiled as Kindle book to #{mobi}"
+ Kindle.generate(output_dir, mobi, out)
puts "(kindlegen log at #{out})."
end
diff --git a/guides/rails_guides/kindle.rb b/guides/rails_guides/kindle.rb
new file mode 100644
index 0000000000..09eecd5634
--- /dev/null
+++ b/guides/rails_guides/kindle.rb
@@ -0,0 +1,119 @@
+#!/usr/bin/env ruby
+
+unless `which kindlerb`
+ abort "Please gem install kindlerb"
+end
+
+require 'nokogiri'
+require 'fileutils'
+require 'yaml'
+require 'date'
+
+module Kindle
+ extend self
+
+ def generate(output_dir, mobi_outfile, logfile)
+ output_dir = File.absolute_path(output_dir)
+ Dir.chdir output_dir do
+ puts "=> Using output dir: #{output_dir}"
+ puts "=> Arranging html pages in document order"
+ toc = File.read("toc.ncx")
+ doc = Nokogiri::XML(toc).xpath("//ncx:content", 'ncx' => "http://www.daisy.org/z3986/2005/ncx/")
+ html_pages = doc.select {|c| c[:src]}.map {|c| c[:src]}.uniq
+
+ generate_front_matter(html_pages)
+
+ generate_sections(html_pages)
+
+ generate_document_metadata(mobi_outfile)
+
+ puts "Creating MOBI document with kindlegen. This make take a while."
+ cmd = "kindlerb . > #{File.absolute_path logfile} 2>&1"
+ puts cmd
+ system(cmd)
+ puts "MOBI document generated at #{File.expand_path(mobi_outfile, output_dir)}"
+ end
+ end
+
+ def generate_front_matter(html_pages)
+ frontmatter = []
+ html_pages.delete_if {|x|
+ if x =~ /(toc|welcome|credits|copyright).html/
+ frontmatter << x unless x =~ /toc/
+ true
+ end
+ }
+ html = frontmatter.map {|x|
+ Nokogiri::HTML(File.open(x)).at("body").inner_html
+ }.join("\n")
+
+ fdoc = Nokogiri::HTML(html)
+ fdoc.search("h3").each do |h3|
+ h3.name = 'h4'
+ end
+ fdoc.search("h2").each do |h2|
+ h2.name = 'h3'
+ h2['id'] = h2.inner_text.gsub(/\s/, '-')
+ end
+ add_head_section fdoc, "Front Matter"
+ File.open("frontmatter.html",'w') {|f| f.puts fdoc.to_html}
+ html_pages.unshift "frontmatter.html"
+ end
+
+ def generate_sections(html_pages)
+ FileUtils::rm_rf("sections/")
+ html_pages.each_with_index do |page, section_idx|
+ FileUtils::mkdir_p("sections/%03d" % section_idx)
+ doc = Nokogiri::HTML(File.open(page))
+ title = doc.at("title").inner_text.gsub("Ruby on Rails Guides: ", '')
+ title = page.capitalize.gsub('.html', '') if title.strip == ''
+ File.open("sections/%03d/_section.txt" % section_idx, 'w') {|f| f.puts title}
+ doc.xpath("//h3[@id]").each_with_index do |h3,item_idx|
+ subsection = h3.inner_text
+ content = h3.xpath("./following-sibling::*").take_while {|x| x.name != "h3"}.map {|x| x.to_html}
+ item = Nokogiri::HTML(h3.to_html + content.join("\n"))
+ item_path = "sections/%03d/%03d.html" % [section_idx, item_idx]
+ add_head_section(item, subsection)
+ item.search("img").each do |img|
+ img['src'] = "#{Dir.pwd}/#{img['src']}"
+ end
+ item.xpath("//li/p").each {|p| p.swap(p.children); p.remove}
+ File.open(item_path, 'w') {|f| f.puts item.to_html}
+ end
+ end
+ end
+
+ def generate_document_metadata(mobi_outfile)
+ puts "=> Generating _document.yml"
+ x = Nokogiri::XML(File.open("rails_guides.opf")).remove_namespaces!
+ cover_jpg = "#{Dir.pwd}/images/rails_guides_kindle_cover.jpg"
+ cover_gif = cover_jpg.sub(/jpg$/, 'gif')
+ puts `convert #{cover_jpg} #{cover_gif}`
+ document = {
+ 'doc_uuid' => x.at("package")['unique-identifier'],
+ 'title' => x.at("title").inner_text.gsub(/\(.*$/, " v2"),
+ 'publisher' => x.at("publisher").inner_text,
+ 'author' => x.at("creator").inner_text,
+ 'subject' => x.at("subject").inner_text,
+ 'date' => x.at("date").inner_text,
+ 'cover' => cover_gif,
+ 'masthead' => nil,
+ 'mobi_outfile' => mobi_outfile
+ }
+ puts document.to_yaml
+ File.open("_document.yml", 'w'){|f| f.puts document.to_yaml}
+ end
+
+ def add_head_section(doc, title)
+ head = Nokogiri::XML::Node.new "head", doc
+ title_node = Nokogiri::XML::Node.new "title", doc
+ title_node.content = title
+ title_node.parent = head
+ css = Nokogiri::XML::Node.new "link", doc
+ css['rel'] = 'stylesheet'
+ css['type'] = 'text/css'
+ css['href'] = "#{Dir.pwd}/stylesheets/kindle.css"
+ css.parent = head
+ doc.at("body").before head
+ end
+end
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 42794b180e..dd57787111 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -143,7 +143,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
* `ActiveSupport::JSON::Variable` is deprecated. Define your own `#as_json` and `#encode_json` methods for custom JSON string literals.
-* Deprecates the compatibility method Module#local_constant_names, use Module#local_constants instead (which returns symbols).
+* Deprecates the compatibility method Module#local_constant_names, use Module#local_constants instead (which returns symbols).
* BufferedLogger is deprecated. Use ActiveSupport::Logger, or the logger from Ruby stdlib.
@@ -165,8 +165,48 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railt
### Notable changes
+* Adds some metadata columns to `schema_migrations` table.
+
+ * `migrated_at`
+ * `fingerprint` - an md5 hash of the migration.
+ * `name` - the filename minus version and extension.
+
+* Adds PostgreSQL array type support. Any datatype can be used to create an array column, with full migration and schema dumper support.
+
+* Add `Relation#load` to explicitly load the record and return `self`.
+
+* `Model.all` now returns an `ActiveRecord::Relation`, rather than an array of records. Use `Relation#to_a` if you really want an array. In some specific cases, this may cause breakage when upgrading.
+
+* Added `ActiveRecord::Migration.check_pending!` that raises an error if migrations are pending.
+
+* Added custom coders support for `ActiveRecord::Store`. Now you can set your custom coder like this:
+
+ store :settings, accessors: [ :color, :homepage ], coder: JSON
+
+* `mysql` and `mysql2` connections will set `SQL_MODE=STRICT_ALL_TABLES` by default to avoid silent data loss. This can be disabled by specifying `strict: false` in your `database.yml`.
+
+* Remove IdentityMap.
+
+* Adds `ActiveRecord::NullRelation` and `ActiveRecord::Relation#none` implementing the null object pattern for the Relation class.
+
+* Added `create_join_table` migration helper to create HABTM join tables.
+
+* Allows PostgreSQL hstore records to be created.
+
### Deprecations
+* Deprecated the old-style hash based finder API. This means that methods which previously accepted "finder options" no longer do.
+
+* All dynamic methods except for `find_by_...` and `find_by_...!` are deprecated. Here's
+ how you can rewrite the code:
+
+ * `find_all_by_...` can be rewritten using `where(...)`.
+ * `find_last_by_...` can be rewritten using `where(...).last`.
+ * `scoped_by_...` can be rewritten using `where(...)`.
+ * `find_or_initialize_by_...` can be rewritten using `where(...).first_or_initialize`.
+ * `find_or_create_by_...` can be rewritten using `find_or_create_by(...)` or `where(...).first_or_create`.
+ * `find_or_create_by_...!` can be rewritten using `find_or_create_by!(...)` or `where(...).first_or_create!`.
+
Credits
-------
diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md
index 68c6416e89..883c2dda4a 100644
--- a/guides/source/active_record_basics.md
+++ b/guides/source/active_record_basics.md
@@ -5,9 +5,11 @@ This guide is an introduction to Active Record.
After reading this guide, you will know:
-* What Object Relational Mapping and Active Record are and how they are used in Rails.
+* What Object Relational Mapping and Active Record are and how they are used in
+ Rails.
* How Active Record fits into the Model-View-Controller paradigm.
-* How to use Active Record models to manipulate data stored in a relational database.
+* How to use Active Record models to manipulate data stored in a relational
+ database.
* Active Record schema naming conventions.
* The concepts of database migrations, validations and callbacks.
@@ -16,19 +18,34 @@ After reading this guide, you will know:
What is Active Record?
----------------------
-Active Record is the M in [MVC](getting_started.html#the-mvc-architecture) - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.
+Active Record is the M in [MVC](getting_started.html#the-mvc-architecture) - the
+model - which is the layer of the system responsible for representing business
+data and logic. Active Record facilitates the creation and use of business
+objects whose data requires persistent storage to a database. It is an
+implementation of the Active Record pattern which itself is a description of an
+Object Relational Mapping system.
### The Active Record Pattern
-Active Record was described by Martin Fowler in his book _Patterns of Enterprise Application Architecture_. In Active Record, objects carry both persistent data and behavior which operates on that data. Active Record takes the opinion that ensuring data access logic is part of the object will educate users of that object on how to write to and read from the database.
+Active Record was described by Martin Fowler in his book _Patterns of Enterprise
+Application Architecture_. In Active Record, objects carry both persistent data
+and behavior which operates on that data. Active Record takes the opinion that
+ensuring data access logic is part of the object will educate users of that
+object on how to write to and read from the database.
### Object Relational Mapping
-Object-Relational Mapping, commonly referred to as its abbreviation ORM, is a technique that connects the rich objects of an application to tables in a relational database management system. Using ORM, the properties and relationships of the objects in an application can be easily stored and retrieved from a database without writing SQL statements directly and with less overall database access code.
+Object-Relational Mapping, commonly referred to as its abbreviation ORM, is
+a technique that connects the rich objects of an application to tables in
+a relational database management system. Using ORM, the properties and
+relationships of the objects in an application can be easily stored and
+retrieved from a database without writing SQL statements directly and with less
+overall database access code.
### Active Record as an ORM Framework
-Active Record gives us several mechanisms, the most important being the ability to:
+Active Record gives us several mechanisms, the most important being the ability
+to:
* Represent models and their data
* Represent associations between these models
@@ -39,14 +56,30 @@ Active Record gives us several mechanisms, the most important being the ability
Convention over Configuration in Active Record
----------------------------------------------
-When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating Active Record models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason.
+When writing applications using other programming languages or frameworks, it
+may be necessary to write a lot of configuration code. This is particularly true
+for ORM frameworks in general. However, if you follow the conventions adopted by
+Rails, you'll need to write very little configuration (in some case no
+configuration at all) when creating Active Record models. The idea is that if
+you configure your applications in the very same way most of the times then this
+should be the default way. In this cases, explicit configuration would be needed
+only in those cases where you can't follow the conventions for any reason.
### Naming Conventions
-By default, Active Record uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class `Book`, you should have a database table called **books**. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the CamelCase form, while the table name must contain the words separated by underscores. Examples:
+By default, Active Record uses some naming conventions to find out how the
+mapping between models and database tables should be created. Rails will
+pluralize your class names to find the respective database table. So, for
+a class `Book`, you should have a database table called **books**. The Rails
+pluralization mechanisms are very powerful, being capable to pluralize (and
+singularize) both regular and irregular words. When using class names composed
+of two or more words, the model class name should follow the Ruby conventions,
+using the CamelCase form, while the table name must contain the words separated
+by underscores. Examples:
* Database Table - Plural with underscores separating words (e.g., `book_clubs`)
-* Model Class - Singular with the first letter of each word capitalized (e.g., `BookClub`)
+* Model Class - Singular with the first letter of each word capitalized (e.g.,
+`BookClub`)
| Model / Class | Table / Schema |
| ------------- | -------------- |
@@ -59,34 +92,52 @@ By default, Active Record uses some naming conventions to find out how the mappi
### Schema Conventions
-Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns.
-
-* **Foreign keys** - These fields should be named following the pattern `singularized_table_name_id` (e.g., `item_id`, `order_id`). These are the fields that Active Record will look for when you create associations between your models.
-* **Primary keys** - By default, Active Record will use an integer column named `id` as the table's primary key. When using [Rails Migrations](migrations.html) to create your tables, this column will be automatically created.
-
-There are also some optional column names that will create additional features to Active Record instances:
-
-* `created_at` - Automatically gets set to the current date and time when the record is first created.
-* `created_on` - Automatically gets set to the current date when the record is first created.
-* `updated_at` - Automatically gets set to the current date and time whenever the record is updated.
-* `updated_on` - Automatically gets set to the current date whenever the record is updated.
-* `lock_version` - Adds [optimistic locking](http://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to a model.
-* `type` - Specifies that the model uses [Single Table Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)
-* `(table_name)_count` - Used to cache the number of belonging objects on associations. For example, a `comments_count` column in a `Post` class that has many instances of `Comment` will cache the number of existent comments for each post.
+Active Record uses naming conventions for the columns in database tables,
+depending on the purpose of these columns.
+
+* **Foreign keys** - These fields should be named following the pattern
+ `singularized_table_name_id` (e.g., `item_id`, `order_id`). These are the
+ fields that Active Record will look for when you create associations between
+ your models.
+* **Primary keys** - By default, Active Record will use an integer column named
+ `id` as the table's primary key. When using [Rails
+ Migrations](migrations.html) to create your tables, this column will be
+ automatically created.
+
+There are also some optional column names that will create additional features
+to Active Record instances:
+
+* `created_at` - Automatically gets set to the current date and time when the
+ record is first created.
+* `updated_at` - Automatically gets set to the current date and time whenever
+ the record is updated.
+* `lock_version` - Adds [optimistic
+ locking](http://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to
+ a model.
+* `type` - Specifies that the model uses [Single Table
+ Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)
+* `(table_name)_count` - Used to cache the number of belonging objects on
+ associations. For example, a `comments_count` column in a `Post` class that
+ has many instances of `Comment` will cache the number of existent comments
+ for each post.
NOTE: While these column names are optional, they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, `type` is a reserved keyword used to designate a table using Single Table Inheritance (STI). If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
Creating Active Record Models
-----------------------------
-It is very easy to create Active Record models. All you have to do is to subclass the `ActiveRecord::Base` class and you're good to go:
+It is very easy to create Active Record models. All you have to do is to
+subclass the `ActiveRecord::Base` class and you're good to go:
```ruby
class Product < ActiveRecord::Base
end
```
-This will create a `Product` model, mapped to a `products` table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. Suppose that the `products` table was created using an SQL sentence like:
+This will create a `Product` model, mapped to a `products` table at the
+database. By doing this you'll also have the ability to map the columns of each
+row in that table with the attributes of the instances of your model. Suppose
+that the `products` table was created using an SQL sentence like:
```sql
CREATE TABLE products (
@@ -96,7 +147,8 @@ CREATE TABLE products (
);
```
-Following the table schema above, you would be able to write code like the following:
+Following the table schema above, you would be able to write code like the
+following:
```ruby
p = Product.new
@@ -107,9 +159,12 @@ puts p.name # "Some Book"
Overriding the Naming Conventions
---------------------------------
-What if you need to follow a different naming convention or need to use your Rails application with a legacy database? No problem, you can easily override the default conventions.
+What if you need to follow a different naming convention or need to use your
+Rails application with a legacy database? No problem, you can easily override
+the default conventions.
-You can use the `ActiveRecord::Base.table_name=` method to specify the table name that should be used:
+You can use the `ActiveRecord::Base.table_name=` method to specify the table
+name that should be used:
```ruby
class Product < ActiveRecord::Base
@@ -117,7 +172,9 @@ class Product < ActiveRecord::Base
end
```
-If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the `set_fixture_class` method in your test definition:
+If you do so, you will have to define manually the class name that is hosting
+the fixtures (class_name.yml) using the `set_fixture_class` method in your test
+definition:
```ruby
class FunnyJoke < ActiveSupport::TestCase
@@ -127,7 +184,8 @@ class FunnyJoke < ActiveSupport::TestCase
end
```
-It's also possible to override the column that should be used as the table's primary key using the `ActiveRecord::Base.set_primary_key` method:
+It's also possible to override the column that should be used as the table's
+primary key using the `ActiveRecord::Base.set_primary_key` method:
```ruby
class Product < ActiveRecord::Base
@@ -138,19 +196,24 @@ end
CRUD: Reading and Writing Data
------------------------------
-CRUD is an acronym for the four verbs we use to operate on data: **C**reate, **R**ead, **U**pdate and **D**elete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables.
+CRUD is an acronym for the four verbs we use to operate on data: **C**reate,
+**R**ead, **U**pdate and **D**elete. Active Record automatically creates methods
+to allow an application to read and manipulate data stored within its tables.
### Create
-Active Record objects can be created from a hash, a block or have their attributes manually set after creation. The `new` method will return a new object while `create` will return the object and save it to the database.
+Active Record objects can be created from a hash, a block or have their
+attributes manually set after creation. The `new` method will return a new
+object while `create` will return the object and save it to the database.
-For example, given a model `User` with attributes of `name` and `occupation`, the `create` method call will create and save a new record into the database:
+For example, given a model `User` with attributes of `name` and `occupation`,
+the `create` method call will create and save a new record into the database:
```ruby
user = User.create(name: "David", occupation: "Code Artist")
```
-Using the `new` method, an object can be created without being saved:
+Using the `new` method, an object can be instantiated without being saved:
```ruby
user = User.new
@@ -160,7 +223,8 @@ user.occupation = "Code Artist"
A call to `user.save` will commit the record to the database.
-Finally, if a block is provided, both `create` and `new` will yield the new object to that block for initialization:
+Finally, if a block is provided, both `create` and `new` will yield the new
+object to that block for initialization:
```ruby
user = User.new do |u|
@@ -171,7 +235,8 @@ end
### Read
-Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record.
+Active Record provides a rich API for accessing data within a database. Below
+are a few examples of different data access methods provided by Active Record.
```ruby
# return array with all records
@@ -193,11 +258,13 @@ david = User.find_by_name('David')
users = User.where(name: 'David', occupation: 'Code Artist').order('created_at DESC')
```
-You can learn more about querying an Active Record model in the [Active Record Query Interface](active_record_querying.html) guide.
+You can learn more about querying an Active Record model in the [Active Record
+Query Interface](active_record_querying.html) guide.
### Update
-Once an Active Record object has been retrieved, its attributes can be modified and it can be saved to the database.
+Once an Active Record object has been retrieved, its attributes can be modified
+and it can be saved to the database.
```ruby
user = User.find_by_name('David')
@@ -205,9 +272,26 @@ user.name = 'Dave'
user.save
```
+A shorthand for this is to use a hash mapping attribute names to the desired
+value, like so:
+
+```ruby
+user = User.find_by_name('David')
+user.update_attributes(name: 'Dave')
+```
+
+This is most useful when updating several attributes at once. If, on the other
+hand, you'd like to update several records in bulk, you may find the
+`update_all` class method useful:
+
+```ruby
+User.update_all "max_login_attempts = 3, must_change_password = 'true'"
+```
+
### Delete
-Likewise, once retrieved an Active Record object can be destroyed which removes it from the database.
+Likewise, once retrieved an Active Record object can be destroyed which removes
+it from the database.
```ruby
user = User.find_by_name('David')
@@ -217,14 +301,70 @@ user.destroy
Validations
-----------
-Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the [Active Record Validations and Callbacks guide](active_record_validations_callbacks.html#validations-overview).
+Active Record allows you to validate the state of a model before it gets written
+into the database. There are several methods that you can use to check your
+models and validate that an attribute value is not empty, is unique and not
+already in the database, follows a specific format and many more.
+
+Validation is a very important issue to consider when persisting to database, so
+the methods `create`, `save` and `update_attributes` take it into account when
+running: they return `false` when validation fails and they didn't actually
+perform any operation on database. All of these have a bang counterpart (that
+is, `create!`, `save!` and `update_attributes!`), which are stricter in that
+they raise the exception `ActiveRecord::RecordInvalid` if validation fails.
+A quick example to illustrate:
+
+```ruby
+class User < ActiveRecord::Base
+ validates_presence_of :name
+end
+
+User.create # => false
+User.create! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
+```
+
+You can learn more about validations in the [Active Record Validations
+guide](active_record_validations.html).
Callbacks
---------
-Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the [Active Record Validations and Callbacks guide](active_record_validations_callbacks.html#callbacks-overview).
+Active Record callbacks allow you to attach code to certain events in the
+life-cycle of your models. This enables you to add behavior to your models by
+transparently executing code when those events occur, like when you create a new
+record, update it, destroy it and so on. You can learn more about callbacks in
+the [Active Record Callbacks guide](active_record_callbacks.html).
Migrations
----------
-Rails provides a domain-specific language for managing a database schema called migrations. Migrations are stored in files which are executed against any database that Active Record support using rake. Rails keeps track of which files have been committed to the database and provides rollback features. You can learn more about migrations in the [Active Record Migrations guide](migrations.html)
+Rails provides a domain-specific language for managing a database schema called
+migrations. Migrations are stored in files which are executed against any
+database that Active Record support using `rake`. Here's a migration that
+creates a table:
+
+```ruby
+class CreatePublications < ActiveRecord::Migration
+ def change
+ create_table :publications do |t|
+ t.string :title
+ t.text :description
+ t.references :publication_type
+ t.integer :publisher_id
+ t.string :publisher_type
+ t.boolean :single_issue
+
+ t.timestamps
+ end
+ add_index :publications, :publication_type_id
+ end
+end
+```
+
+Rails keeps track of which files have been committed to the database and
+provides rollback features. To actually create the table, you'd run `rake db:migrate`
+and to roll it back, `rake db:rollback`.
+
+Note that the above code is database-agnostic: it will run in MySQL, postgresql,
+Oracle and others. You can learn more about migrations in the [Active Record
+Migrations guide](migrations.html)
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 95adb4ff0a..dd59e2a8df 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -94,6 +94,25 @@ end
NOTE: `belongs_to` associations _must_ use the singular term. If you used the pluralized form in the above example for the `customer` association in the `Order` model, you would be told that there was an "uninitialized constant Order::Customers". This is because Rails automatically infers the class name from the association name. If the association name is wrongly pluralized, then the inferred class will be wrongly pluralized too.
+The corresponding migration might look like this:
+
+```ruby
+class CreateOrders < ActiveRecord::Migration
+ def change
+ create_table :customers do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :orders do |t|
+ t.belongs_to :customer
+ t.datetime :order_date
+ t.timestamps
+ end
+ end
+end
+```
+
### The `has_one` Association
A `has_one` association also sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model. For example, if each supplier in your application has only one account, you'd declare the supplier model like this:
@@ -106,6 +125,25 @@ end
![has_one Association Diagram](images/has_one.png)
+The corresponding migration might look like this:
+
+```ruby
+class CreateSuppliers < ActiveRecord::Migration
+ def change
+ create_table :suppliers do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :accounts do |t|
+ t.belongs_to :supplier
+ t.string :account_number
+ t.timestamps
+ end
+ end
+end
+```
+
### The `has_many` Association
A `has_many` association indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a `belongs_to` association. This association indicates that each instance of the model has zero or more instances of another model. For example, in an application containing customers and orders, the customer model could be declared like this:
@@ -120,6 +158,25 @@ NOTE: The name of the other model is pluralized when declaring a `has_many` asso
![has_many Association Diagram](images/has_many.png)
+The corresponding migration might look like this:
+
+```ruby
+class CreateCustomers < ActiveRecord::Migration
+ def change
+ create_table :customers do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :orders do |t|
+ t.belongs_to :customer
+ t.datetime :order_date
+ t.timestamps
+ end
+ end
+end
+```
+
### The `has_many :through` Association
A `has_many :through` association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding _through_ a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:
@@ -143,6 +200,31 @@ end
![has_many :through Association Diagram](images/has_many_through.png)
+The corresponding migration might look like this:
+
+```ruby
+class CreateAppointments < ActiveRecord::Migration
+ def change
+ create_table :physicians do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :patients do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :appointments do |t|
+ t.belongs_to :physician
+ t.belongs_to :patient
+ t.datetime :appointment_date
+ t.timestamps
+ end
+ end
+end
+```
+
The collection of join models can be managed via the API. For example, if you assign
```ruby
@@ -199,6 +281,31 @@ end
![has_one :through Association Diagram](images/has_one_through.png)
+The corresponding migration might look like this:
+
+```ruby
+class CreateAccountHistories < ActiveRecord::Migration
+ def change
+ create_table :suppliers do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :accounts do |t|
+ t.belongs_to :supplier
+ t.string :account_number
+ t.timestamps
+ end
+
+ create_table :account_histories do |t|
+ t.belongs_to :account
+ t.integer :credit_rating
+ t.timestamps
+ end
+ end
+end
+```
+
### The `has_and_belongs_to_many` Association
A `has_and_belongs_to_many` association creates a direct many-to-many connection with another model, with no intervening model. For example, if your application includes assemblies and parts, with each assembly having many parts and each part appearing in many assemblies, you could declare the models this way:
@@ -215,6 +322,29 @@ end
![has_and_belongs_to_many Association Diagram](images/habtm.png)
+The corresponding migration might look like this:
+
+```ruby
+class CreateAssembliesAndParts < ActiveRecord::Migration
+ def change
+ create_table :assemblies do |t|
+ t.string :name
+ t.timestamps
+ end
+
+ create_table :parts do |t|
+ t.string :part_number
+ t.timestamps
+ end
+
+ create_table :assemblies_parts do |t|
+ t.belongs_to :assembly
+ t.belongs_to :part
+ end
+ end
+end
+```
+
### Choosing Between `belongs_to` and `has_one`
If you want to set up a one-to-one relationship between two models, you'll need to add `belongs_to` to one, and `has_one` to the other. How do you know which is which?
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 446f767f0c..a8e33a2956 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -276,6 +276,8 @@ config.middleware.delete ActionDispatch::BestStandardsSupport
* `config.active_record.auto_explain_threshold_in_seconds` configures the threshold for automatic EXPLAINs (`nil` disables this feature). Queries exceeding the threshold get their query plan logged. Default is 0.5 in development mode.
+* +config.active_record.cache_timestamp_format+ controls the format of the timestamp value in the cache key. Default is +:number+.
+
The MySQL adapter adds one additional configuration option:
* `ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns in a MySQL database to be booleans and is true by default.
diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md
index 79d59859c8..db43d62fcf 100644
--- a/guides/source/development_dependencies_install.md
+++ b/guides/source/development_dependencies_install.md
@@ -145,6 +145,9 @@ We need first to delete `.bundle/config` because Bundler remembers in that file
In order to be able to run the test suite against MySQL you need to create a user named `rails` with privileges on the test databases:
```bash
+$ mysql -uroot -p
+
+mysql> CREATE USER 'rails'@'localhost';
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.*
to 'rails'@'localhost';
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.*
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index d7c648681d..e779407fab 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -9,6 +9,10 @@
name: Models
documents:
-
+ name: Active Record Basics
+ url: active_record_basics.html
+ description: This guide will get you started with models, persistence to database and the Active Record pattern and library.
+ -
name: Rails Database Migrations
url: migrations.html
description: This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 54200768e6..02ec024e5b 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -215,11 +215,7 @@ Open the `app/views/welcome/index.html.erb` file in your text editor and edit it
### Setting the Application Home Page
-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>. At the moment, however, the "Welcome Aboard" smoke test is occupying that spot.
-
-To fix this, delete the `index.html` file located inside the `public` directory of the application.
-
-You need to do this because Rails will serve any static file in the `public` directory that matches a route in preference to any dynamic content you generate from the controllers. The `index.html` file is special: it will be served if a request comes in at the root route, e.g. <http://localhost:3000>. If another request such as <http://localhost:3000/welcome> happened, a static file at `public/welcome.html` would be served first, but only if it existed.
+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>. At the moment, "Welcome Aboard" is occupying that spot.
Next, you have to tell Rails where your actual home page is located.
@@ -233,7 +229,6 @@ Blog::Application.routes.draw do
# first created -> highest priority.
# ...
# You can have the root of your site routed with "root"
- # just remember to delete public/index.html.
# root to: "welcome#index"
```
@@ -558,7 +553,7 @@ parameter, which in our case will be the id of the post. Note that this
time we had to specify the actual mapping, `posts#show` because
otherwise Rails would not know which action to render.
-As we did before, we need to add the `show` action in
+As we did before, we need to add the `show` action in
`app/controllers/posts_controller.rb` and its respective view.
```ruby
diff --git a/guides/source/index.html.erb b/guides/source/index.html.erb
index 71fe94a870..a8e4525c67 100644
--- a/guides/source/index.html.erb
+++ b/guides/source/index.html.erb
@@ -9,9 +9,7 @@ Ruby on Rails Guides
<% content_for :index_section do %>
<div id="subCol">
<dl>
- <dd class="kindle">Rails Guides are also available for Kindle and <%= link_to 'Free Kindle Reading Apps', 'http://www.amazon.com/gp/kindle/kcp' %> for the iPad,
-iPhone, Mac, Android, etc. Download them from <%= link_to 'here', @mobi %>.
- </dd>
+ <dd class="kindle">Rails Guides are also available for <%= link_to 'Kindle', @mobi %>.</dd>
<dd class="work-in-progress">Guides marked with this icon are currently being worked on and will not be available in the Guides Index menu. While still useful, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections.</dd>
</dl>
</div>
diff --git a/guides/source/kindle/rails_guides.opf.erb b/guides/source/kindle/rails_guides.opf.erb
index 4e07664fd0..547abcbc19 100644
--- a/guides/source/kindle/rails_guides.opf.erb
+++ b/guides/source/kindle/rails_guides.opf.erb
@@ -32,7 +32,7 @@
<item id="toc" media-type="application/x-dtbncx+xml" href="toc.ncx" />
- <item id="cover" media-type="image/jpeg" href="images/rails_guides_kindle_cover.jpg"/>
+ <item id="cover" media-type="image/jpg" href="images/rails_guides_kindle_cover.jpg"/>
</manifest>
<spine toc="toc">