Railsでワクワク個人開発 　第5回: CRUD処理の規制と温度/湿度の登録

# 他ユーザーがCRUD処理できないようにする
　少しだけ涼しくなってきた。朝の開発が心地よくなっている。今のコードでは自分以外のユーザーでも植物のCRUD処理ができてしまうので、それをなくしていこう。`plant_controller.rb`へ`before action`を追加する

```ruby:app/controllers/plants_controller.rb 

class PlantsController < ApplicationController
  before_action :move_to_index, except: [:index, :show]

#----中略----
  def move_to_index
    # 自分以外のユーザーの植物の 編集/削除/新規作成はできない
    if (user_signed_in?)    
      if (params[:user_id].to_i != current_user.id)
        redirect_to action: :index
      end
    elsif
        redirect_to action: :index
    end
  end
#----中略----
end
```

before_actionはこのコントローラー内のアクションがよびだされたときにはじめに実行される。今回は`move_to_index`というメソッドが実行されるように指定した。`move_to_index`ではログインしていてかつログインIDと表示したページのuseridが一致しているときだけなにも起こらない。それ以外の場合はindexアクションが実行されるようになっている。
つまりは植物一覧ページへ飛ぶ。

# 温度湿度の表示

　いよいよこんなかんじになってきた。所有している植物の温度と湿度を登録できるようにする。以前のDB設計の際に考えていた`growth_record`を追加することにしよう。

`rails g model growth_record`をターミナルで実行してmodelをつくる。

growth_reocerdテーブルへ各種カラムを書き込む。

```ruby:db/migrate/20200821194548_create_growth_records.rb 
class CreateGrowthRecords < ActiveRecord::Migration[6.0]
  def change
    create_table :growth_records do |t|
      t.integer :plant_id, null: false
      t.datetime :record_time
      t.float :temp, null: false
      t.float :humid, null: false
      t.timestamps
    end
  end
end
```

temp（温度）とhumid（湿度）はfloat型で小数点を記録できるようにした。record_timeはまだ実装していないのでnullでも大丈夫なようにした。

次は`rails g controller growth_reocords`でコントローラーを作成する。

```ruby:app/controllers/growth_records_controller.rb
class GrowthRecordsController < ApplicationController
  def index
    @user = User.find(params[:user_id])
    @plants = @user.plants
    @growth_record = @plants.growth_record
  end
end
```

modelどうしの関連づけをする必要がある。

```ruby:app/models/growth_record.rb 
class GrowthRecord < ApplicationRecord
  belongs_to :plant
end
```

```ruby:app/models/plant.rb 
class Plant < ApplicationRecord
  belongs_to :user
  has_many :growth_record
end
```

今回は植物のgrowth_recordのindexページへは飛ばない。植物詳細ページの内容がかわるだけである。だからroutes.rbの記述に変更はない。かわりに植物のコントローラーとviewファイルが変更される。

```ruby:app/controllers/plants_controller.rb 
#---中略---
  def show
    @user = User.find(params[:user_id])
    @plant = @user.plants.find(params[:id])
    @growth_record = @plant.growth_record #　←　追加
  end
#---中略---
```

```erb:app/views/plants/show.html.erb
<h3>植物の名前</h3>
<%= @plant.plant_name %><br>
<h3> 植物の写真　</h3>
<%= @plant.img %><br> 
<%= @plant.img %><br>
<h3> 温度/湿度　</h3>
<!-- 追加↓-->
<% @growth_record.each do |g| %>
  <li>日時：<%= g.record_time %> / 　温度：<%= g.temp %>  /湿度：<%= g.humid %>  </li> 
<% end %> 
```

これでOK。ついでにseedデータも修正しておこう。

```ruby:db/seed.rb
# ----中略-----
GrowthRecord.create(plant_id:1, record_time: "r22ose", temp: 25.2, humid:50.3)
GrowthRecord.create(plant_id:1, record_time: "r22ose", temp: 24.2, humid:70.3) 
GrowthRecord.create(plant_id:1, record_time: "r22ose", temp: 21.2, humid:60.3) 
GrowthRecord.create(plant_id:1, record_time: "r22ose", temp: 20.2, humid:30.3)  
GrowthRecord.create(plant_id:2, record_time: "ro33se", temp: 25.6, humid:30.3) 

```

よし。


# 温度湿度のCRUD処理
　この記事もきりの良いところまで進めてしまおう。温度と湿度のCRUD処理ができるようする。まずはroutes.rbを修正しよう。

```ruby:config/routes.rb
Rails.application.routes.draw do
  root to: 'users#index'
  devise_for :users

  resources :users do
    resources :plants do
      resources :growth_records, shallow: true # 追加
    end
  end
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

```

　`shallow`というオプションがあることに気づいた。railsガイドの浅いネストにある。
[Rails のルーティング - Railsガイド](https://railsguides.jp/routing.html#%E3%80%8C%E6%B5%85%E3%81%84%E3%80%8D%E3%83%8D%E3%82%B9%E3%83%88)


>この方法は、ルーティングの記述を複雑にせず、かつ深いネストを作らないという絶妙なバランスを保っています。:shallowオプションを使うことで、上と同じ内容をさらに簡単に記述できます。

これにより、show/edit/update/destroyアクションはネストの外にいくようになる。ターミナルでrails routesを打ちながら確認しよう。

```
            user_plant_growth_records GET    /users/:user_id/plants/:plant_id/growth_records(.:format)                                growth_records#index
                                      POST   /users/:user_id/plants/:plant_id/growth_records(.:format)                                growth_records#create
         new_user_plant_growth_record GET    /users/:user_id/plants/:plant_id/growth_records/new(.:format)                            growth_records#new
                   edit_growth_record GET    /growth_records/:id/edit(.:format)                                                       growth_records#edit
                        growth_record GET    /growth_records/:id(.:format)                                                            growth_records#show
                                      PATCH  /growth_records/:id(.:format)                                                            growth_records#update
                                      PUT    /growth_records/:id(.:format)                                                            growth_records#update
                                      DELETE /growth_records/:id(.:format)                                                            growth_records#destroy
```

コントローラーやviewファイルは植物のCRUD処理の場合とあまり変わらず実装できた。よかった。


# おまけ：「植物詳細」へ戻るリンクが難しかった
　個人的に難しかったのがひとつあった。linkのurlである。今まではCRUD処理の後はマイページへ戻る仕様にしていたのでlinkの張り方は迷わなかった。以下のような形。

```erb
<%= link_to 'マイページへ', user_path(current_user.id) %>  
```

　でも、温度湿度のCRUD処理をした後はその植物の詳細ページへ戻るようにしたかった。いろいろ悩んだけど以下のようになった。

```erb:app/views/growth_records/create.html.erb 
<%= link_to '詳細ページ', user_plant_path(current_user.id,@plant.id) %> 
```

```erb:app/views/growth_records/destroy.html.erbまたはupdate.html.erb
<%= link_to '詳細ページ', user_plant_path(current_user.id,@growth_record.plant_id) %> 
```

pathの指定で()の中に複数の値を指定できることがわかった。

# binding.pryでデバッグするのが便利
　やっとおわった。ちょっと詰まったところはbinding.pryをつかって中の変数を観察するようにした。するとうまくいった。

　単純にエラー文をググるだけでは全然うまくいかない。OKだったときとエラーができるときの差分を自分の中ではっきりと持つことが重要だった。そうして変数をいじったり場合を分けたりしてその差分を徐々に詰めていく…。

　「この場合ではOKだったけどこうしたらNGだった」そんなイメージで。

　一区切りついた。次はrspecのテストを試してみよう。