Rails in a nutshell Глава 3. Active Record

Cody Fauser, James MacAulay, Edward Ocampo-Gooding, John Guenin, “Rails in a nutshell Chapter 3. Active Record”, public translation into Russian from English More about this translation.

Translate into another language.

Глава 3. Active Record

Подключение к базе данных

Перед тем как Active Record сможет выполнять какую либо свою ORM магию, оно должно знать с каким типом баз данных оно будет работать и как ему подключаться к этой базе. В Rails приложении это решается небольшим конфигурационным файлом находящемся в config/database.yml. Rails загружает настройки объявленные в этом файле, располагает их в хэше доступном через ActiveRecord::Base.configurations, и использует их для установления соединения с базой данных. По умолчанию, только что сгенерированное приложение имеет базовые настройки базы данных, которые позволяют запустить приложение без какого либо предварительного конфигурирования. Файл database.yml по умолчанию выглядит так:

# SQLite version 3.x

# gem install sqlite3-ruby (не нужно на OS X Leopard)

development:

adapter: sqlite3

database: db/development.sqlite3

pool: 5

timeout: 5000

# Предупреждение: База данных определенная как "test" будет стерта и

# будет пересоздана из базы development когда вы запустите "rake"

# Не указывайте базу одинаковым именем для development или production разработки.

test:

adapter: sqlite3

database: db/test.sqlite3

pool: 5

timeout: 5000

production:

adapter: sqlite3

database: db/production.sqlite3

pool: 5

timeout: 5000

В данном случае свойства адаптера установлены таким образом, что каждая среда разработки получит свою собственную базу данных для работы. Вам будет нужно иметь установленную библиотеку sqlite3-ruby до того, как све зарботает должным образом. SQLite3 сохраняет базу данных как единственный файл в месте указанным в свойстве для каждой конфигурации среды разработки и каждая база создается автоматически, если она еще не существует. Свойство 'pool' определяет максимальное количество соединений к базе в пуле соединений Active Record. Свойство 'timeout' является специальным в описании адаптера SQLite3 и обсуждается в .....???

Если вы хотите, чтобы новое Rails приложение было сгенерировано с другим адаптером базы данных, вы можете использовать параметр --database:

$ rails myapp --database=mysql

Это создаст другой database.yml, потому что адаптер MySQL работает иначе и требует другой набор данных для управления подключениями. Параметры для настройки каждого адаптера, подробно изложены в ???.

До тех пока вы не используете SQLite адаптеры, вам возможно придется создавать базу приложения в ручную. К счастью, Rails предоставляет задачу, которая собирает все действия в одну команду:

$ rake db:create

Как многие другие команды Rails, db:create смотрит значение переменной окружения с именем RAILS_ENV, чтобы определить с какой средой приложения нужно взаимодействовать, применяя настройки по умолчанию. Это означает, что выше указанная команда создала бы базу среды приложения с именем (именем файла в случае с SQLite) равным значению ActiveRecord::Base.configurations ['development']['database']. Если необходимо создать базу для всех сред приложения указанных в файле database.yml одним махом, то есть и команда предназначеная для этого:

1 comment

1.

Alan Da Costa Posted 1 day and 3 hours ago

* "to operate on" => "to operate in"

* sp "withe" => "with the" ; maybe consider replacing with, "in the"

$ rake db:create:all

Tip

Each Rails environment uses a completely separate database configuration, so each could use a different database adapter if that's what you want. For example you might find it most convenient to use SQLite3 for development, but want some features of PostgreSQL for your live application. The downside to this kind of setup is that differences in the way various database adapters work can remain hidden while you work in development mode, only to produce surprise results in a production environment. As a general rule, it is wise to keep the configurations of your various environments as close to one another as possible.

A Model's Names

Part of Rails' convention-over-configuration approach involves naming things in unsurprising ways so that the framework doesn't need to be told how to find things. Each ActiveRecord model in a Rails application is a subclass of ActiveRecord::Base, and it should follow the ruby convention of having capitalized CamelCase class names. The model's filename should be like the class name, but all in underscored lowercase. So a School model would be defined in school.rb, and a CourseEnrollment model would be defined in course_enrollment.rb.

The other name associated with a model is its database table name, which is like the file's base name but also pluralized. School records live in the schools table; CourseEnrollment records live in the course_enrollments table.

Developing your Database Schema with Migrations

After your application has a database to work with, you can start populating it with the tables and columns that define the foundation of your data model: the schema. The primary means of developing the schema is by creating a number of small Ruby files called migrations. A typical Rails application will end up with a growing number of migrations as development progresses and the schema evolves. Each migrations forms a link in a sequential chain of alterations to the database schema. The migration files are stored in db/migrate and each one usually consists of just a single class with two method definitions: up and down. Here's what we get when we run the migration generator:

$ script/generate migration СreateUsersAndClouds

create db/migrate

create db/migrate/20090610033819_create_users_and_clouds.rb

We gave the generator the name of the migration, and it created a single file for us. The long string of numbers at the beginning of the filename is a timestamp from whenever the migration is generated. This is how Rails maintains a consistent ordering of migrations and keeps track of which migrations have already been run. Here is the migration skeleton which has been generated for us:

class CreateUsersAndClouds < ActiveRecord::Migration

def self.up

end

def self.down

end

end

The file contains a subclass of ActiveRecord::Migration using the name we passed to the generator. The up method is going to contain the changes we want to make to our schema; the down method is going define how those changes can be undone. The application we're creating here is going to allow people to contribute URLs to images of clouds on the web, and to enter

1 comment

1.

Alan Da Costa Posted 1 day and 3 hours ago

broken paragraph

Here, we want to create a table for users of the application and

1 comment

1.

Alan Da Costa Posted 1 day and 3 hours ago

broken paragraph

Associations

One of the key differences between relational databases and object-oriented systems is the way that hierarchical data is represented. In an object-oriented program, a School object might have many Student objects associated with it, with the School keeping track of its Students by storing references to them in a collection object of some kind. In a relational database, however, it is the child entities which keep track of the parents: each row in the students table would reference an associated row in the schools table by storing its school's primary key in a special column in the students table. As long as an index is maintained for the foreign key column, queries to find either a particular student's school or a particular school's students can be completed very quickly without the database having to look at each student row one at a time.

This is a very good thing, but it can be very unintuitive for object-oriented programmers to suddenly have to think about relationships in this way. Wouldn't it be nice if we could just type out school.students and get back what we expect? Yes it would, and here's how you do it with ActiveRecord:

class School < ActiveRecord::Base

has_many :students

end

Besides the schools table itself, all this requires is a students table with a column called school_id. The has_many method is a class method on ActiveRecord::Base which, among other things, dynamically defines a public instance method on School called students. This method returns an array-like object which gives access to all the student records which have the school's id in their school_id column.

Примечание

The object returned by the students method looks a whole lot like a standard Ruby Array:

school = School.first

# => #<School id: 1, name: "Lisgar Collegiate Institute">

school.students[0..1].map(&:name)

# => ["Jimmy", "Jane"]

school.students.class

# => Array

But beware: even while that object tells you with a straight face that it's an Array, it is lying to you. Most of the time you can treat it like an Array and you wouldn't notice the difference, but really it is an instance of ActiveRecord::Associations::AssociationProxy with a lot more smarts behind it than a simple Array. It's good to keep this in mind when that association object doesn't behave quite the way you expect it to.

By calling the has_many method in the School class, we are defining an association on that class, and Active Record does a fair bit of work behind the scenes to keep track of the association and provide convenient ways for you to manage a record's relationships with other records. In order to get the same kind of convenience on the other side of the school-student relationship, we would make a similar declaration in the Student class:

class Student < ActiveRecord::Base

belongs_to :school

end

Note

Associations don't really need to be reciprocated; that is, a has_many declaration does not need a corresponding belongs_to in the associated model in order to function correctly. It usually makes things easier if you declare both sides of an association, though, especially when other developers are exploring your code.

belongs_to

The belongs_to association is defined on the model with the foreign key column in its table. This declaration is used for both one-to-one and one-to-many associations; a model with a belongs_to declaration doesn't care whether or not there are other records in its table with the same foreign key. Continuing the example above, the Student class would get the following instance methods when its belongs_to class method is called with :school:

school

Returns a School object representing the associated school record in the database; that is, the school with an id equal to the school_id attribute in the Student object. Returns nil if no record is found.

school=(new_school)

Assigns the given School object to the Student object's association and sets the school_id of the student to the id of the school.

build_school(attributes)

Initializes a new School object with the given attributes and assigns it to the Student, but does not save the newly built object. Since the unsaved school doesn't yet have a primary key assigned from the database, the student's school_id is left untouched until both halves of the association are saved.

create_school(attributes)

Like build_school, but saves both objects in the association.

has_one

A has_one association declares a one-to-one relationship on a model that does not hold the foreign key. If we have a MailingAddress model, we might say that a Student has_one MailingAddress:

class Student < ActiveRecord::Base

belongs_to :school

has_one :mailing_address

Pages: ← previous Ctrl next
1 2 3

© CC

Original (English): Rails in a nutshell Chapter 3. Active Record

Translation: © skr1p7, blandger, GremL1N, Elrick .

License: CC

translated.by crowd

Like this translation? Share it or bookmark!