RDR3T > Ассоциации и отношения между моделями. Валидация.

апреля 14, 2011  |  Published in Ruby on Rails, Ruby on Rails 3  |  17 Comments

Я немного изменил планы и в этой статье не будет рассматриваться работа с RSpec, зато написанию спецификаций будет посвящена целая отдельная статья.

Итак, у нас имеется модель User, которая представляет собой пользователя нашего приложения. В данной статье мы создадим модель Post и контроллер PostsController, которые позволят нам ввести в приложение новую сущность и новый ресурс Post. Post представляет собой публикацию в блоге.

Поскольку любая публикация в блоге должна публиковаться от имени определенного пользователя, то нам необходимо определить связь (ассоциацию) между двумя моделями. Поскольку пользователь может иметь несколько публикаций, а публикация только одного автора, то нам следует установить отношение между моделями: User имеет много Post‘ов. Но прежде, давайте создадим модель и контроллер для работы с постами, а для этого создадим специальную ветку в нашем проекте и будем работать в ней:

$ git branch posts

Теперь если вы воспользуетесь командой, то увидите следущий ответ:

$ git branch
* master
posts

Звездочкой отмечена текущая ветка, для переключения на ветку posts следует воспользоваться командой:

$ git checkout posts
Switched to branch ‘posts’

Вы также могли бы создать ветку сразу из git checkout:

$ git checkout -b posts

Теперь, когда ветка posts создана и мы на нее переключились, мы можем заняться разработкой модели, контролера и представлений поста. В прошлой статье я обещал рассказать вам как создавать модели, контроллеры и другие компоненты приложения при помощи других встроенных в Rails генераторов, кроме scaffold. Сразу скажу, что в данной статье мы будем использовать стандартный генератор scaffold так как код генерируемый им нам весьма подходит, хотя код контроллера мы слегка упростим, чтобы он был идентичен коду из контроллера UsersController.

Для отдельной генерации моделей, контроллеров и так далее следует использовать команды:

rails g controller Posts
rails g model Post title:string text:text user_id:integer
rails g migration create_posts

Вместо всего этого мы, для упрощения работы, воспользуемся генератором scaffold:

rails g scaffold Post title:string content:text user_id:integer

Теперь, давайте отредактируем код контроллера так, чтобы он имел следущий вид:

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def show
    @post = Post.find(params[:id])
  end

  def new
    @post = Post.new
  end

  def edit
    @post = Post.find(params[:id])
  end

  def create
    @post = Post.new(params[:post])
    @post.save ? redirect_to(@post, :notice => 'Post was successfully created.') : render(:action => "new")
  end

  def update
    @post = Post.find(params[:id])
    @post.update_attributes(params[:post]) ? redirect_to(@post, :notice => 'Post was successfully updated.') : (render :action => "edit")
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy and redirect_to(posts_url)
  end
end

Теперь, разобравшись со второстепенными заданиями давайте перейдем к самой сути главы — отношениям между сущностями (моделями).

Модели в Rails могут иметь разные типы отношений: has_one (одном экземпляру принадлежит другой единственный экземпляр), has_many (одному экземпляру принадлежит несколько других экземпляров), belongs_to (экземпляр принадлежит другому экземпляру) и has_and_belongs_to_many. Для полного понимания того, что такое отношения (ассоциации), я кратко объясню что это на примере нашего проекта. Каждый пост (статья) в разрабатываемом блоге не может существовать просто так, она должна иметь пользователя — автора, другими словами пост принадлежит (belongs_to) пользователю. В это же время пользователь владеет постом, причем может владеть не одним, а некоторым количеством постов, то есть пользователь has_many :posts. Еще пользователь может иметь, например один номер телефона. Когда одной сущности может принадлежать только один экземпляр другой, то такое отношение описывается через has_one. Для того, чтобы установить отношения между моделями в нашем приложении, мы должны прописать в каждой модели эти отношения:

#post.rb модель
class Post < ActiveRecord::Base
  belongs_to :user
end

#user.rb модель
class User < ActiveRecord::Base
  has_many :posts
end

Давайте откроем консоль и поиграемся с нашими моделями, чтобы лучше узнать как работают отношения.

$ rails c
user = User.new do |u|
  u.name = 'Vasya'
  u.lname = 'Petrov'
  u.login = 'vaspet'
  u.password = 'pass123'
  u.email = 'vasya@petrov.ru'
end
#=> #<User id: nil, name: "Vasya", lname: "Petrov", login: "vaspet", password: "pass123", email: "vasya@petrov.ru", created_at: nil, updated_at: nil>

user.save #=> true

user.posts #=> []

post = Post.new do |p|
  p.title = "First post"
  p.content = "First blog post. First blog bost..."
end
#=> #<Post id: nil, title: "First post", content: "First blog post. First blog bost...", user_id: nil, created_at: nil, updated_at: nil>

user.posts << post
#=> [#<Post id: 1, title: "First post", content: "First blog post. First blog bost...", user_id: 1, created_at: "2011-04-13 17:20:48", updated_at: "2011-04-13 17:20:48">]

user.save #=> true

user.posts
#=> [#<Post id: 1, title: "First post", content: "First blog post. First blog bost...", user_id: 1, created_at: "2011-04-13 17:20:48", updated_at: "2011-04-13 17:20:48">]

post.user
#=> #<User id: 1, name: "Vasya", lname: "Petrov", login: "vaspet", password: "pass123", email: "vasya@petrov.ru", created_at: "2011-04-13 17:16:55", updated_at: "2011-04-13 17:16:55">

Поскольку пост не может существовать сам по себе, то есть не может существовать без автора, то вам следует указать значение зависимости постов от пользователя в значение :destroy:

class User < ActiveRecord::Base
  has_many :posts, :dependent =>:destroy
end

Теперь, при удалении пользователя вместе с ним будут удалены все его посты.

Также вам следует заняться валидацией ваших моделей. Валидация — это процесс проверки данных записанных в экземпляр модели перед его сохранением в базу данных. В результате валидации вы можете множество проверок, которые бы обеспечивали: полноту данных, качество данных, безопасность. В нашем примере нам необходимо проверить указан ли у поста его автор, если автор не указан, то пост не будет сохранен. Кроме проверки наличия автора у поста мы позаботимся о проверке других атрибутов экземпляров обеих моделей:

#models/user.rb
class User < ActiveRecord::Base
  validates :name,     :presence => true
  validates :lname,    :presence => true
  validates :password, :presence => true
  validates :login,    :presence => true, :uniqueness => true
  validates :email,    :presence => true, :uniqueness => true

  has_many :posts, :dependent =>:destroy
end

#models/post.rb
class Post < ActiveRecord::Base
  validates :user_id, :presence => true
  validates :title,   :presence => true
  validates :content, :presence => true

  belongs_to :user
end

Метод validates принимает в качестве аргументов имя проверяемого поля и тип проверки. :presence => true, означает что мы проверяем то, имеются ли в проверяемом поле какие-нибудь данные, а параметр :uniqueness => true, позволяет проверить уникальность данных введенных в поле. В нашем случае логин и адрес электронной почты должны не могут повторяться. Написание большого количества проверок считается хорошим тоном. Хотя время записи данных в базу увеличится, зато ваше приложение будет защищено от случайного или преднамеренного ввода неправильных данных, и будет требовать от пользования ввода всех необходимых для работы данных.

Только что мы закончили работу с постами, а значит, следует сделать коммит, слить ветку posts с веткой master и отправить изменения в удаленный репозиторий на GitHub:

$ git status
# On branch posts
# Changed but not updated:
#   (use «git add <file>…» to update what will be committed)
#   (use «git checkout — <file>…» to discard changes in working directory)
#
#    modified:   app/models/user.rb
#    modified:   config/routes.rb
#    modified:   db/schema.rb
#
# Untracked files:
#   (use «git add <file>…» to include in what will be committed)
#
#    app/controllers/posts_controller.rb
#    app/helpers/posts_helper.rb
#    app/models/post.rb
#    app/views/posts/
#    db/migrate/20110406172137_create_posts.rb
#    spec/controllers/posts_controller_spec.rb
#    spec/helpers/posts_helper_spec.rb
#    spec/models/post_spec.rb
#    spec/requests/posts_spec.rb
#    spec/routing/posts_routing_spec.rb
#    spec/views/posts/
no changes added to commit (use «git add» and/or «git commit -a»)

$ git commit -am ‘add posts’
[posts ef18d24] add posts
3 files changed, 18 insertions(+), 1 deletions(-)

$ git checkout master
Switched to branch ‘master’

$ git merge posts
Updating f29d0da..ef18d24
Fast-forward
app/models/user.rb |    7 +++++++
config/routes.rb   |    2 ++
db/schema.rb       |   10 +++++++++-
3 files changed, 18 insertions(+), 1 deletions(-)
$ git status
# On branch master
# Your branch is ahead of ‘origin/master’ by 1 commit.
#
# Untracked files:
#   (use «git add <file>…» to include in what will be committed)
#
#    app/controllers/posts_controller.rb
#    app/helpers/posts_helper.rb
#    app/models/post.rb
#    app/views/posts/
#    db/migrate/20110406172137_create_posts.rb
#    spec/controllers/posts_controller_spec.rb
#    spec/helpers/posts_helper_spec.rb
#    spec/models/post_spec.rb
#    spec/requests/posts_spec.rb
#    spec/routing/posts_routing_spec.rb
#    spec/views/posts/
nothing added to commit but untracked files present (use «git add» to track)

$ git commit -am ‘add posts’
[master 4af1c38] add posts
18 files changed, 427 insertions(+), 0 deletions(-)
create mode 100644 app/controllers/posts_controller.rb
create mode 100644 app/helpers/posts_helper.rb
create mode 100644 app/models/post.rb
create mode 100644 app/views/posts/_form.html.erb
create mode 100644 app/views/posts/edit.html.erb
create mode 100644 app/views/posts/index.html.erb
create mode 100644 app/views/posts/new.html.erb
create mode 100644 app/views/posts/show.html.erb
create mode 100644 db/migrate/20110406172137_create_posts.rb
create mode 100644 spec/controllers/posts_controller_spec.rb
create mode 100644 spec/helpers/posts_helper_spec.rb
create mode 100644 spec/models/post_spec.rb
create mode 100644 spec/requests/posts_spec.rb
create mode 100644 spec/routing/posts_routing_spec.rb
create mode 100644 spec/views/posts/edit.html.erb_spec.rb
create mode 100644 spec/views/posts/index.html.erb_spec.rb
create mode 100644 spec/views/posts/new.html.erb_spec.rb
create mode 100644 spec/views/posts/show.html.erb_spec.rb

$ git push origin
Counting objects: 64, done.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (45/45), 6.76 KiB, done.
Total 45 (delta 7), reused 0 (delta 0)
To git@github.com:egoholic/blog.git
f29d0da..4af1c38  master -> master

Кроме модели User и Post, наш блог должен иметь модель Category, экземпляры которой представляют собой категории постов. В нашем блоге пост может принадлежать сразу нескольким категориям, а категория может иметь сразу несколько постов. Такие отношения называются отношения многие ко многим.

Давайте создадим модель Category и затем опишем отношения между ею и моделью Post. Для этого удалим ветку проекта posts и создадим новую ветку categories:

$ git branch -d posts
Deleted branch posts (was ef18d24).

$ git checkout -b categories
Switched to a new branch ‘categories’

Каждое новое более-менее значительное изменение в проекте следует выполнять в новой ветке и сейчас мы будем работать в ветке categories.

Создать отношение многие-ко многим можно в несколько способов, при помощи ассоциации has_many и параметра :through, и ассоциации has_and_belongs_to_many. Поскольку ассоциация has_and_belongs_to_many является моветоном и имеет несколько проблем, то использовать мы будем ассоциацию has_many :through. Используя ассоциацию has_and_belongs_to_many, вы создаете отношение многие ко многим напрямую при помощи дополнительной таблицы categories_posts. Когда же вы используете ассоциацию has_many :through, то отношение многие ко многим создается через дополнительную модель, которая также использует таблицу categories_posts, где хранятся записи состоящие из пар post_id и category_id, по которым можно произвести выборку всех записей с определенным category_id, а затем, по полю post_id этих записей сделать выборку постов из таблицы posts.

Для начала воспользуемся генератором scaffold для генерации модели Category и контроллера CategoriesController:

$ rails g scaffold Category name:string count:integer
invoke  active_record
create    db/migrate/20110414133930_create_categories.rb
create    app/models/category.rb
invoke    rspec

identical    public/stylesheets/scaffold.css

Теперь, нам необходимо создать промежуточную модель CategoryPost:

$ rails g model CategoryPost post_id:integer category_id:integer
invoke  active_record
create    db/migrate/20110414135111_create_category_posts.rb
create    app/models/category_post.rb
invoke    rspec
create      spec/models/category_post_spec.rb

Теперь выполним миграции, которые были созданы генераторами:

$ rake db:migrate
(in /home/vladimir/proj/blog)
==  CreateCategories: migrating ===============================================
— create_table(:categories)
-> 0.0183s
==  CreateCategories: migrated (0.0184s) ======================================

==  CreateCategoryPosts: migrating ============================================
— create_table(:category_posts)
-> 0.0049s
==  CreateCategoryPosts: migrated (0.0050s) ===================================

После того, как таблицы и модели созданы, необходимо заняться описанием отношений между таблицами:

#models/category_post.rb
class CategoryPost < ActiveRecord::Base
  belongs_to :post
  belongs_to :category
end

#models/post.rb
class Post < ActiveRecord::Base
  validates :user_id, :presence => true
  validates :title,   :presence => true
  validates :content, :presence => true

  belongs_to :user
  has_many :category_posts, :dependent => :destroy
  has_many :categories, :through => :category_posts
end

#models/category.rb
class Category < ActiveRecord::Base
  has_many :category_posts
  has_many :posts, :through => :category_posts
end

Давайте запустим консоль и подробно рассмотрим как устроены отношения между моделями:

user = User.new do |u|
  u.name = 'Vladimir'
  u.lname = 'Melnik'
  u.login = 'admin'
  u.password = '12345'
  u.email = 'egotraumatic@gmail.com'
end
#=> #<User id: nil, name: "Vladimir", lname: "Melnik", login: "admin", password: "12345", email: "egotraumatic@gmail.com", created_at: nil, updated_at: nil>

user.save #=> true

category = Category.new(name: 'Ruby')
#=> #<Category id: nil, name: "Ruby", count: nil, created_at: nil, updated_at: nil>

category.save #=> true

category2 = Category.new(name: 'Rails')
#=> #<Category id: nil, name: "Rails", count: nil, created_at: nil, updated_at: nil>

category2.save #=> true

post = Post.new(title: "First post", content: "First Vladimir's blog post.")
#=> #<Post id: nil, title: "First post", content: "First Vladimir's blog post.", user_id: nil, created_at: nil, updated_at: nil>

user.posts << post
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">]

user.save #=> true

category.posts << post
=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">]

category.save #=> true

category2.posts << post
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">]

category2.save #=> true

post2 = Post.new(title: 'Second post', content: 'Second Vladimir's blog post')

user.posts << post2
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">, #<Post id: 2, title: "Second post", content: "Second Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:14:13", updated_at: "2011-04-14 14:28:15">]

category2.posts << post2
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">, #<Post id: 2, title: "Second post", content: "Second Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:14:13", updated_at: "2011-04-14 14:28:15">]

user.save #=> true

category.save #=> true

user.posts
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">, #<Post id: 2, title: "Second post", content: "Second Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:14:13", updated_at: "2011-04-14 14:28:15">]

category.posts
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">]

category2.posts
#=> [#<Post id: 3, title: "First post", content: "First Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:25:43", updated_at: "2011-04-14 14:25:43">, #<Post id: 2, title: "Second post", content: "Second Vladimir's blog post.", user_id: 2, created_at: "2011-04-14 14:14:13", updated_at: "2011-04-14 14:28:15">]

post.categories
#=> [#<Category id: 3, name: "Ruby", count: nil, created_at: "2011-04-14 14:23:14", updated_at: "2011-04-14 14:23:14">, #<Category id: 4, name: "Rails", count: nil, created_at: "2011-04-14 14:23:31", updated_at: "2011-04-14 14:23:31">]

post2.categories
#=> [#<Category id: 4, name: "Rails", count: nil, created_at: "2011-04-14 14:23:31", updated_at: "2011-04-14 14:23:31">]

Чтобы получить все посты данной категории, необходимо просто вызвать метод #posts у экземпляра категории. Чтобы получить список всех категорий — необходимо вызвать метод #categories у экземпляра поста.

Поскольку, мы уже завершили работу над категориями, следует слить ветки вместе:

$ git commit -am ‘add categories’
[categories 24f1679] add categories
3 files changed, 19 insertions(+), 1 deletions(-)

$ git checkout master
Switched to branch ‘master’

$ git merge categories
Updating 4af1c38..24f1679
Fast-forward
app/models/post.rb |    2 ++
config/routes.rb   |    2 ++
db/schema.rb       |   16 +++++++++++++++-
3 files changed, 19 insertions(+), 1 deletions(-)

$ git commit -m ‘add categories’
[master 1e7e910] add categories
21 files changed, 475 insertions(+), 0 deletions(-)
create mode 100644 app/controllers/categories_controller.rb
create mode 100644 app/helpers/categories_helper.rb

create mode 100644 spec/views/categories/show.html.erb_spec.rb

Итак, мы уже имеем практически полнофункциональный набросок проекта. Для полноты функционала нам необходимо добавить возможность комментирования постов. Каждый пост может иметь множество комментариев, а каждый комментарий может принадлежать одному единственному посту. Это значит, что здесь следует использовать ассоциацию has_many. Комментарии в нашем приложении — блоге будут представлены моделью Comment. Следует также заметить, что комментарий должен принадлежать одному и только одному пользователю, то есть каждый комментарий имеет одинаковые отношения как с постом, так и с пользователем. Давайте создадим модель, контроллер, представления и прочие файлы для комментариев при помощи уже знакомого генератора scaffold. Мы не будем создавать новых веток, а будем работать в ветке master потому, что изменения, которые мы вносим являются достаточно мелкими и проблем с ними возникнуть не должно. В примерах выше новые ветки проекта создавались в целях напомнить вам о работе с системой контроля версий git.

$ rails g scaffold comment title:string comment:text user_id:integer post_id:integer
invoke  active_record
create    db/migrate/20110414151117_create_comments.rb
create    app/models/comment.rb
invoke    rspec

invoke  stylesheets
identical    public/stylesheets/scaffold.css

$ rake db:migrate
(in /home/vladimir/proj/blog)
==  CreateComments: migrating =================================================
— create_table(:comments)
-> 0.0023s
==  CreateComments: migrated (0.0024s) ========================================

А теперь давайте установим отношения между моделями:

#models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end


#models/user.rb
class User < ActiveRecord::Base
  validates :name,     :presence => true
  validates :lname,    :presence => true
  validates :password, :presence => true
  validates :login,    :presence => true, :uniqueness => true
  validates :email,    :presence => true, :uniqueness => true

  has_many :posts,    :dependent => :destroy
  has_many :comments, :dependent => :destroy
end


#models/post.rb
class Post < ActiveRecord::Base
  validates :user_id, :presence => true
  validates :title,   :presence => true
  validates :content, :presence => true

  belongs_to :user
  has_many :category_posts,  :dependent => :destroy
  has_many :categories,      :through => :category_posts
  has_many :comments,        :dependent => :destroy
end

Модель Comment, как и большинство моделей должна быть снабжена валидацией для поверки того, вся ли информация переданная в экземпляр комментариия является корректной:

class Comment < ActiveRecord::Base
  validates :comment, :presence => true
  validates :user_id, :presence => true
  validates :post_id, :presence => true

  belongs_to :user
  belongs_to :post
end

В моделе Comment мы только что добавили проверку на то, что у комментария есть автор, есть пост к которому он относится и есть текст самого комментария.

На этом глава заканчивается, а в следущей, если ничего не поменяется, мы рассмотрим создание многоуровневых (вложенных) комментариев и более подробно познакомимся с работой контроллеров и представлений.

Tags: , ,

Responses

  1. 0x2e says:

    апреля 14, 2011 at 21:00 (#)

    Классно, но все-же жду статью про тестирование, Rspec book тяжеловато идет а найти статьи для чайников в стиле rails+rspec+cucumber+webrat+factory_girls+… нелегко :-)

  2. alp says:

    апреля 15, 2011 at 08:28 (#)

    классно, перевариваем

  3. says:

    апреля 15, 2011 at 08:29 (#)

    2 0x2e
    вместо девченок лучше

  4. dimytch says:

    апреля 15, 2011 at 09:29 (#)

    [quote]
    Поскольку ассоциация [color=blue]has_and_belongs_to_many[/color] является муветоном и имеет несколько проблем,…
    [/quote]

    С этого места очень хотелось бы пояснений: почему плохой тон и какие проблемы?

  5. Павел says:

    апреля 15, 2011 at 11:55 (#)

    Круто, но не устаю повторять, что для новичков вы пишете непонятно

  6. Alexander says:

    апреля 15, 2011 at 16:13 (#)

    А почему использовать связь has_and_belongs_to_many плохо ? и какие могут быть проблеммы при использовании этой чудо асоциации ?

  7. 0x2e says:

    апреля 15, 2011 at 17:09 (#)

    2 Igas
    чем лучше?

  8. admin says:

    апреля 16, 2011 at 15:23 (#)

    Павел, сейчас пишутся черновые версии статей, в дальнейшем они будут поправлены, возможно изменится структура и т.д. Было бы хорошо, если бы вы задали вопросы касательно того, что вам не ясно, я бы на них ответил в комментариях, а позже обновил бы саму статью.

  9. Elka says:

    мая 4, 2011 at 10:21 (#)

    У меня такая ситуация: имеется несколько моделей, для начала две form и father, прописаны связи, в контроллере

    def create
        @form = Form.new(params[:form])
        @father= Father.new()
        respond_to do |format|
          if @form.save and @father.save
            format.html { redirect_to(@form, :notice => 'Отчет успешно отправлен.') }
            format.xml  { render :xml => @form, :status => :created, :location => @form }
          else
            format.html { render :action => "new" }
            format.xml  { render :xml => @form.errors, :status => :unprocessable_entity }
          end
        end
       end

    Проблема в том что в БД сохраняются пустые значения. Данные с формы поля Father_name не передаются.

  10. admin says:

    мая 4, 2011 at 13:03 (#)

    Elka, немного не понял вашу проблему. Если я провильно представил, то, что вы написали, то модель Form принадлежит модели Father и в форме заполняются поля для обеих моделей. Если это так, то вам следует сделать так:

    class Form < ActiveRecord::Base
      belongs_to :father # or has_one :father
      accepts_nested_attributes_for :father
    end
    
    #FormsController
    
      def edit
        @form = Form.new
        @form.father.build
      end
    
    #views/forms/_form.html.erb
    
    <%= form_for(@form) do |f| %>
      #form elements here
        < %= f.fields_for :father do |ff| %>
        #father form elements here
        < % end %>
    < % end %>
    

    Теперь ваша форма может сохранять сразу две модели, одна из которых (Father) — вложенная.

  11. Bighamster says:

    мая 25, 2011 at 12:20 (#)

    Почему в методе has_many используется имя таблицы, а в методе belongs_to имя класса?

  12. admin says:

    мая 25, 2011 at 13:22 (#)

    Bighamster, на самом деле здесь идет привязка не к имени контроллера и таблицы в БД, а к именам сущностей и читабельности кода.

    has_many :comments — означает, что данной сущности принадлежит множество других сущностей — комментариев. has_many :comments читается как обычное предложение: Имеет много КОММЕНТАРИЕВ (множественное число — несколько комментариев).

    belongs_to :post — Принадлежит одному посту (единственное число — один пост).

  13. vladiboc says:

    декабря 26, 2011 at 09:01 (#)

    Устойчиво ругается на вызов user.posts:

    1.9.2p290 :003 > user.posts
    ActiveRecord::StatementInvalid: Could not find table ‘posts’
    [вырезано]
    [sysadmin@sysadmin blog]$ rails —version
    Rails 3.1.3
    [sysadmin@sysadmin blog]$

    Что неправильно?

  14. admin says:

    декабря 26, 2011 at 09:18 (#)

    vladiboc, судя по всему нужно пиграцию для постов сделать…

    $ rake db:migrate

  15. vladiboc says:

    декабря 26, 2011 at 09:44 (#)

    Спасибо, получилось

  16. anonymous says:

    января 26, 2012 at 18:21 (#)

    Отличный материал — спасибо!!!

    зы: правильно пишется мОветон, а не мУветон. поправьте плз :)

  17. admin says:

    января 27, 2012 at 13:36 (#)

    anonymous, спасибо, поправил.

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.