QiitaのRails5アップデート

この資料は8/18日のIncrements meetupの発表資料です。

---

#QiitaのRails5アップデート

## はじめに

- 7月に入社しました
- Railsは3.2が出た時ぐらいから
- attr_accessibleとかあったな〜程度の意識

---

## 無茶振り

yuku 「QiitaをRails5にしたいんだよね」

---

## 終わらなかったので現状を話します

---

## Rails5は何が新しいのか

- ActionCable
- Rails API
- ActiveRecord attributes API
- Turbolinks5
- etc...

--- 

## みたいな話はしません

---

## Rails5ができなくなったこと

- protected_attributesが使えなくなった
- belongs_toがデフォルトではoptionalではなくなった
- Callbackを中断するのに`false`が非推奨に

---

## Qiitaの現状

- attr_accessible, protectedによるMass Assignment対策
- belongs_to optionalを各所で使用している
- callbackはもちろんfalseを返している
- sprockets-railsは2.x
- 自社でforkしてメンテしているライブラリが多数ある

---

## やったこと 

---

## attr_accessible, protectedによるMass Assignment対策

みなさんprotected_attributes、使ってますか？

- [Rails公式がサポートを打ち切っている](https://github.com/rails/rails/commit/f4fbc0301021f13ae05c8e941c8efc4ae351fdf9)
- egrep -rl 'attr_accessible|attr_protected' app/models/ | wc -l  
- → 68個の該当モデル
- どう移行するか

---

## 気合で移行する

--- 

やることは単純

- 既存の実装をテストで網羅し
- attr_*を　取り除き
- controller側をstrong parameterで書き直し
- 不正なparameterを許可していないかテストを加える

```rb
shared_examples_for 'unpermitted parameter rejection' do
  let(:target_attributes) { params.with_indifferent_access[model.class.name.downcase] }

  context 'with unpermitted attributes attributes' do
    it 'does not update' do
      expect { subject }.not_to change { model.reload.attributes }
    end
  end
end
```

現在 進捗 4/68

--- 

## belongs_toがデフォルトではoptionalではなくなった

```rb
config.active_record.belongs_to_required_by_default = false
```

にすれば良い

が、optionalを全てで許容しているのはあまり健全ではない

- テストカバレッジを上げて
- オプションをtrueにできるようにしていく(進捗なし)

--- 

## callbackを中断するのに`false`が使えなくなった

`throw(:abort)` を使う

こんな時に紛らわしかった

```rb
# https://speakerdeck.com/claudiob/better-callbacks-in-rails-5
class User < ActiveRecord::Base
  before_action :set_default_value

  private

  def set_default_value
    self.admin ||= false
  end
end
```

```rb
User.create!
# => ActiveRecord::RecordNotSaved
```

書き換えるのみ

--- 


## あとは...

- これだけではない
    - sprockets-rails3への移行
    - 独自メンテナンスしているリポジトリのupstreamへの追従


--- 

## sprockets-railsのアップデート

- Qiitaはsprocketsを捨てようと作業中
    - JSは@mizchiがbrowserify-railsを使った形式に変更。sprocketsはprecompileのみ行う
    - CSSは@morishitterが移行中 :pray: 

もう少し捨てられないのでアップデートしていく :muscle: 
---

## node_modulesパッケージをsprocketsとつなぐ

CSSの依存もnode_modulesで管理したい

```rb
# Allow stylesheets to import SCSS files from node_modules.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
```

これだと死んでしまう

---

sprockets-railsは `application` と名のつくものすべてをprecompileしようと頑張る

例えば `bootstrap-sass`は `application.css.ejs.scss` というファイルを持っている

こいつらをprecompileに含めるわけにはいかないので、以前は`application.rb`にこう書いていた

```rb
config.assets.precompile = [
  ::Sprockets::Railtie::LOOSE_APP_ASSETS,
  'application.css',
  'application.js',
  'bundle.js',
  'components.js',
　　　　　....
]
```

--- 

これだとできない

sprockets-railsが3.0から `config.assets.precompile`への[デフォルト値のセットのタイミングを変えた](https://github.com/rails/sprockets-rails/pull/329/files#diff-b295f4f07d2e863f15e53eb2047cfd1fR101)

なので `assets.rb` に移動させることで解決する

---

## forkしてメンテナンスしているリポジトリのupstreamへの追従

forkして自社でメンテナンス、と行っても必要なパッチだけをあてて放置してしまうパターンもおおいのでは

- https://github.com/increments/i18n-js
- https://github.com/increments/compass-core
- https://github.com/increments/wicked_pdf

大体そんな感じになっている
本家にPull Requestを送ったり、Qiita側で対応しながらupstreamに追従できるように変更した

---

##　最後に

- Railsが示している移行のパスに乗れるように、普段から意識しておく
- forkは用法用量を守って(頼む)