Rails4 「incompatible character encodings: ASCII-8BIT and UTF-8」エラーが出た
自前でSQLを書いていたら、「incompatible character encodings: ASCII-8BIT and UTF-8」というエラーが出た。
ASCII-8BITとUTF-8が文字列中で混在してしまったようだ。
対策としては、下記のようにエンコーディング指定すればよい。
msg.force_encoding("utf-8")
参考:
Rails 4: incompatible character encodings: UTF-8 and ASCII-8BIT - Stack Overflow
Rails4 タイムゾーンを設定しているのに、Heroku上で日付に時差が生じてしまう
config\application.rbに下記のようにタイムゾーンを東京に設定している。
config.time_zone = 'Tokyo'
しかし、Date.todayなどを使用すると、Heroku上で時差が生じてしまった。
config\application.rbで設定したタイムゾーンを使うには、zoneを使うといいようだ。
Time.zone.now
しかし、Dateにはzoneが使用できないので、Timeを使って日付に変換するといいようだ。
Time.zone.now.to_date
参考:
Heroku で日付時刻の表示(9時間ずれて表示される問題の対処) - わからん
Rails 3: How to get today's date in specific timezone? - Stack Overflow
Rails4 PostgreSQLで数値を降順にソートしたらnullが先頭になってしまった
SQLite3では、点数を降順で並べる下記のようなスコープで、nullが末尾に来ていたが、PostgreSQLだと、nullが先頭に来てしまった。
scope :order_score_desc, -> { order(score: :desc) }
そこで、下記のように、(列名 is null)を追加してあげると、PostgreSQLでもnullが末尾に来た。
scope :order_score_desc, -> { order("(score is null)", score: :desc) }
もちろん、SQLite3でも正常に動作した。
Rails4 3階層のincludesの複数指定
N+1問題解決のため、includesの設定をしていた。
groupがuserを参照しており、userがdepartmentとpostを参照しているとき、groupからdepartmentとpostの両方ををincludesで指定するのにちょっと手間取った。
group → user → department・post
下記のように書いたらうまくいった
@groups = Group.order(:id). includes({user: [:department, :post]})
Rails4 ActiveRecordでorを使用する簡単な方法
以前、ActiveRecordでorを使用する方法を見つけましたが、もっと簡単な方法がありました。
Rails4 ActiveRecordでorを使用する - ayaketanのプログラミング勉強日記
ユーザーが所属を3つ持つことができるとします。
ある所属に属するユーザーを抽出するには、下記のように記載します。
department1_id = User.arel_table[:department1_id] department2_id = User.arel_table[:department2_id] department3_id = User.arel_table[:department3_id] User.where(department1_id.eq(department_id).or(department2_id.eq(department_id)).or(department3_id.eq(department_id)))
スコープにする場合、下記のように記載します。
scope :department_is, ->(department_id) { department1_id = User.arel_table[:department1_id] department2_id = User.arel_table[:department2_id] department3_id = User.arel_table[:department3_id] where(department1_id.eq(department_id).or(department2_id.eq(department_id)).or(department3_id.eq(department_id))) }
Rails4 ヘッダのみのCSVファイルをダウンロードする
CSVファイル読み込みのテンプレートファイルとして、ヘッダのみ記載されたCSVファイルのダウンロードをしたかった。
CSV出力の情報は多かったが、ヘッダのみの情報が少なくてちょっとつまずいたのでメモ。
モデルにメソッド追加
# CSV読み込みのテンプレートデータ作成 def csv_template headers = ["ユーザーアカウント", "パスワード", "パスワード(確認)", "氏名", "所属"] csv_data = CSV.generate(headers: headers, write_headers: true, force_quotes: true) do |csv| csv << [] end csv_data.encode(Encoding::SJIS) end
csvに空のデータを入れないと、ヘッダのみ出力することはできません。
ルーティングの設定
resources :users do collection do get 'template' end
コントローラ追加
# CSVテンプレート def template respond_to do |format| format.csv{ send_data User.csv_template, type: 'text/csv; charset=shift_jis', filename: "users.csv" } end end
ビューにリンクを貼る
<%= link_to 'CSVテンプレート', template_users_path(format: 'csv') %>
Rails4 rspec3に変更したら今まで通っていたテストが失敗した。
rspecのバージョンを3.0.1に上げた後、テストを実行したら、今まで通っていたテストのほとんどが失敗した。
原因は2つあった。
1つ目は、be_trueとbe_falseが、be_truthyとbe_falseyに変更されていたからだった。
be_trueをbe_truthyに、be_falseをbe_falseyに置換した。
2つ目は、spec_helperに下記のコードを書いていたが、typeが使えなくなっていたからだった。
RSpec.configure do |config| config.include Devise::TestHelpers, type: :controller end
typeを使うためには、spec\spec_helper.rbに下記を追加する。
RSpec.configure do |config| config.infer_spec_type_from_file_location! # この行を追加 config.include Devise::TestHelpers, type: :controller end
参考:
Consider renaming `be_true` and `be_false` to `be_truthy` and `be_falsey` · Issue #283 · rspec/rspec-expectations · GitHub
RSpec 3の重要な変更 - 有頂天Ruby