元祖若手のプログラミング奮闘記

元祖若手の奮闘記。主にメモ

Rails3.2.22.5 => 5.1.5 への道

■役たったコマンド

git co feature/rails5.1.5 spec/controllers/

これでブランチの一部をマージできる!地味にうれしい!

bundle exec rails app:update

これで初期設定はほぼやってくれる
Rails4ならこっち

bundle exec rake rails:update

勝手に作られた
configファイル

      create  config/secrets.yml
      create  config/cable.yml
      create  config/puma.rb
      create  config/spring.rb
      create  config/initializers/application_controller_renderer.rb
      create  config/initializers/assets.rb
   identical  config/initializers/backtrace_silencers.rb
      create  config/initializers/cookies_serializer.rb
      create  config/initializers/cors.rb
      create  config/initializers/filter_parameter_logging.rb

逆に設定ファイルがあるせいで
エラーが出ることがある
一応
バックアップファイルとしておいてるけど挙動が不安スグル


■エラー集

Model

・countの罠

ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

こんなエラーがでたら

test = model.select("aaa, bbb, ccc").where(hoge: 0)

してから

test.count

をすると

select count(aaa, bbb, ccc) from hage where hoge = 0;

というようなSQLが発行され
Syntaxエラーになる

正解はこちら

test.size

・has_many, has_one, be_longsto系
conditios,orderは今後一切使えないので

has_one :hoge, order: :hoge_rank, condtions: ["hoge_rank >= 0", 0]
has_one :hoge, -> { where("hoge_rank >= ?", 0).order(:hoge_rank) } 

と修正
そもそもconditiosが必要ないModel設計が
今回のバージョンアップで一番大切だと学んだ
正直これ直すのめちゃ辛かった。

・undefined method `sanitize`
Rails5から

ActiveRecord::Base::sanitize

は使えなくなりました!


・Modelから通常のハッシュクラスにしたい

users = User.where(sex: 1).map(&:attributes)

これでなるので
to_jsonにするときとかは非常に大事だと思う


MySQL geometry型

位置情報で使われるgeometry型
Rails5からto_jsonするとこけるようになった
今回はGem入れて変換とかじゃなくて
使われてなかったので値を消した。

・eager_loadで勘違い
モデルのincludesは
preload => joins しない
eager_load => joins する
って感じらしいのとプラス
基本は
preload が使用されるらしい

ちなみにConfigのeager_load
はTrueであると
modelとは一切関係なく
サーバー起動前にapp配下のオブジェクトのNilCheckをしてくれるというやさしいやつ

・join, orderの書き方

User.joins(:item).order(:num)

というようなOrderの書き方に注意

Rails3だと

select users.* from users inner join items on items.user_id = users.id order by num;

と発行されるが
Rails5だと

select users.* from users inner join items on items.user_id = users.id order by users.num;

になるので
usersテーブルにnumカラムがないとエラーが起きるぞ!
ちゃんと

order("#{Item.table_name}.num")

と書こう!

・NOT NULL制約のカラムは入力必須に

Rails3は見ていなかったが
Rails5からはNOT NULL制約をみるようになった

usersテーブル
name NOT NULL
age NOT NULL

だとしたら

user = User.new
user.name = "hogehoge"
user.save

でエラーになる(当たり前っちゃ当たり前だが)

user.age = 100

も追加しよう


・belongs_to の罠
valid?っでかなり変なエラーが追加されるのでなんぞや??
って調べまくっていたら
relationで設定されている値がNullになっていると
エラーを出すようになったらしい。
Nullの可能性もあるよって時は

optional: true

をbelongs_toの最後に追加することで解決した


・配列と見せかけActiveRecode::Relationクラス

users = ::User.where(status: 0).all
# Rails5だとエラーになる
users << ::User.where(status: 1).all

また
普通の配列のようにslice
を使うと
これは配列じゃないだよと怒り出すので

User.all.to_a.slice(1, 3)

見たいに使おう

Controller

Javascriptでアクセスされてもいい場合

Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.
protect_from_forgery except: :index

見たいな書き方でエラーではなくなる


・before_filterはうごかないぜ
before_actionへ切り替えや!

・params permit
ちゃんとしろよ!
permit してないのに

params[:user][:name].gsub(/ruby/, "perl")

とかしたらおこだぞ!


・Browserクラスの引数が変更

# botの場合はログに残さない
ua = URI.decode(request["HTTP_USER_AGENT"])
browser = Browser.new(ua: ua)

こんなコードを見つけたんだが

正しくは

browser = Browser.new(ua)

である

ActionController::Parametersオブジェクトに対して
with_indifferent_accessは使えない

with_indifferent_access
とはHash変数の引数を文字列でもシンボルでも受け取れるようになる関数

使用するためには

.to_h.with_indifferent_access

としなくてはいけない

・render text
はもう使えない

render plain: "OK"

に変更

Route

・asオプションに注意

get 'hoge', to: 'hoge#index' as: 'hoge'
get 'huge/:id', to: 'hoge#show', as: 'hoge' # => 二個あるよ!エラー

・match 使うなら
vi オプションでHTTPメソッドの指定をしないといけなくなりました!

match 'admin' => 'admin#show', via: :get

ActiveRecord::PendingMigrationError

未実行のマイグレーションファイルがあるぜ
Rails3は未実行でもエラーを起こさなかったことが逆にすごい。。

Rspec

Rspec unknown keywordについて
Rails5限定みたい

get :show, id: 1

だとだめで
正しくは

get :show, params: { id: 1 }

とparams変数に入れないといけない

Rails 5 からコントローラーのテストで assigns などを使う場合

rails-controller-testing

gem 必要です!
さらにいうとrequest specへ
移行することが好ましいようです!

レンダリングページ

expect(response).to render_template("hogehoge")

こんな書き方をしていたら
Controller名も追加してテンプレート名を正しい値を入れる

expect(response).to render_template("hage/_hogehohge")

その他


・invalid byte sequence in UTF-8
これが厄介すぎる
普通の文字列のはずなのに
なぜかUTF-8じゃないって怒られて

image_tag
javascript_include_tag
stylesheet_link_tag
とか一切動かない
fileコマンド打ってみたらasciiがあったけども。。

=> 原因不明のままだが
Scssファイルの構文エラーを直し

bundle exec rails precompile

したら直る


・scssの設定がこけるこける
@include
@mixin not found
なんとかしないと

https://rubygems.org

正規表現のエラー

The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?

先頭、末尾を

^ $

から

\A \z

を使用
大体モデルで使ってるので
モデルに記載して終了


Cookieの形が違う

TypeError (incompatible marshal file format (can't be read)
    format version 4.8 required; 123.34 given):

意外とガッツリはまったw

bundle exec rails app:update

で作成された下記ファイル
config/initializers/cookies_serializer.rb

ails.application.config.action_dispatch.cookies_serializer = :json

と指定していたらいつの間にか
上のエラーが出てびっくりした
ブラウザキャッシュを消すことで
収まったがこの設定はもう必要ないかな。。

・lib配下のモジュールを使う
config/application.rb
に下記を追加することで
lib配下のモジュールを使うことができた

config.paths.add 'lib', eager_load: true

・ブロック無しのlink_toは引数の数を三つ以内じゃないとエラー

link_to("hoge", "https://hogehoge/hage", a_options, b_options) => ×
link_to("hoge", "https://hogehoge/hage", a_options.reverse_merge(b_options)) => ○

JqueryのVerによって書き方違った

$('a[href^=#hoge-]').on('click', function() {});

unrecognized expressionとエラーがでて
失敗するので

$('a[href^="#hoge-"]').on('click', function() {});

とかいてクォーテーションで囲もう