railsの多対多のアソシエーション

#はじめに
多対多のアソシエーションっていつも頭がこんがらがるので忘備録

#とりあえず下準備

```
rails new app
rails g model post body:string
rails g model category name:string
rails g model category_post post:references category:references
rails db:migrate
```

これで準備完了

多対多のアソシエーションを行う場合中間テーブルが必要で名前は"modelの名前_modelの名前"です。

後はmodelのファイルに

```ruby:post.rb
has_many :category_posts

has_many :categories, through: :category_posts
```

```ruby:category.rb
has_many :category_posts
has_many :posts, through: :category_posts
```

```ruby:category_post.rb
belongs_to :post 
belongs_to :category
```

と追加する。

なぜかよくわからないけどpost.rb,category.rbのhas_manyの順番が逆だとうまくいかない。



#試しに使ってみる。


試しに使ってみる。

```ruby 

 post = Post.create(body: 'hello world')
   (0.1ms)  begin transaction
  Post Create (2.6ms)  INSERT INTO "posts" ("body", "created_at", "updated_at") VALUES (?, ?, ?)  [["body", "hello world"], ["created_at", "2019-01-02 15:29:45.573338"], ["updated_at", "2019-01-02 15:29:45.573338"]]
   (12.6ms)  commit transaction
=> #<Post id: 3, body: "hello world", created_at: "2019-01-02 15:29:45", updated_at: "2019-01-02 15:29:45", category_id: nil>

post.categories.create(name: 'fun!!')
   (0.0ms)  begin transaction
  Category Create (2.7ms)  INSERT INTO "categories" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "fun!!"], ["created_at", "2019-01-02 15:30:13.503425"], ["updated_at", "2019-01-02 15:30:13.503425"]]
  CategoryPost Create (0.1ms)  INSERT INTO "category_posts" ("post_id", "category_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["post_id", 3], ["category_id", 3], ["created_at", "2019-01-02 15:30:13.507951"], ["updated_at", "2019-01-02 15:30:13.507951"]]
   (12.0ms)  commit transaction
=> #<Category id: 3, name: "fun!!", created_at: "2019-01-02 15:30:13", updated_at: "2019-01-02 15:30:13", post_id: nil>


 post.categories.create(name: '楽しい')
   (0.1ms)  begin transaction
  Category Create (2.8ms)  INSERT INTO "categories" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "楽しい"], ["created_at", "2019-01-02 15:31:44.766487"], ["updated_at", "2019-01-02 15:31:44.766487"]]
  CategoryPost Create (0.1ms)  INSERT INTO "category_posts" ("post_id", "category_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["post_id", 3], ["category_id", 4], ["created_at", "2019-01-02 15:31:44.771663"], ["updated_at", "2019-01-02 15:31:44.771663"]]
   (11.7ms)  commit transaction
=> #<Category id: 4, name: "楽しい", created_at: "2019-01-02 15:31:44", updated_at: "2019-01-02 15:31:44", post_id: nil>
```

こんな感じで勝手に中間テーブルも作成してくれるので

```ruby
 post.categories
  Category Load (0.2ms)  SELECT  "categories".* FROM "categories" INNER JOIN "category_posts" ON "categories"."id" = "category_posts"."category_id" WHERE "category_posts"."post_id" = ? LIMIT ?  [["post_id", 3], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Category id: 3, name: "fun!!", created_at: "2019-01-02 15:30:13", updated_at: "2019-01-02 15:30:13", post_id: nil>, #<Category id: 4, name: "楽しい", created_at: "2019-01-02 15:31:44", updated_at: "2019-01-02 15:31:44", post_id: nil>]>
```

みたいにカテゴリ一覧が取得できる。

中間テーブルが作成されることによってpostはたくさんのカテゴリを持つことができるしカテゴリもたくさんのpostを持つことができる。

例として逆も行ってみる。


```ruby 
category = Category.last
  Category Load (0.3ms)  SELECT  "categories".* FROM "categories" ORDER BY "categories"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<Category id: 4, name: "楽しい", created_at: "2019-01-02 15:31:44", updated_at: "2019-01-02 15:31:44", post_id: nil>

category.posts.create(body: 'everyday ruby')
   (0.0ms)  begin transaction
  Post Create (1.1ms)  INSERT INTO "posts" ("body", "created_at", "updated_at") VALUES (?, ?, ?)  [["body", "everyday ruby"], ["created_at", "2019-01-02 15:35:02.541378"], ["updated_at", "2019-01-02 15:35:02.541378"]]
  CategoryPost Create (0.1ms)  INSERT INTO "category_posts" ("post_id", "category_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["post_id", 4], ["category_id", 4], ["created_at", "2019-01-02 15:35:02.544299"], ["updated_at", "2019-01-02 15:35:02.544299"]]
   (14.4ms)  commit transaction
=> #<Post id: 4, body: "everyday ruby", created_at: "2019-01-02 15:35:02", updated_at: "2019-01-02 15:35:02", category_id: nil>


category.posts
  Post Load (0.3ms)  SELECT  "posts".* FROM "posts" INNER JOIN "category_posts" ON "posts"."id" = "category_posts"."post_id" WHERE "category_posts"."category_id" = ? LIMIT ?  [["category_id", 4], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Post id: 3, body: "hello world", created_at: "2019-01-02 15:29:45", updated_at: "2019-01-02 15:29:45", category_id: nil>, #<Post id: 4, body: "everyday ruby", created_at: "2019-01-02 15:35:02", updated_at: "2019-01-02 15:35:02", category_id: nil>]>
```

問題なく取得できてる。


おわり。