概要

テスト用のfixturesとseedデータを$ rails db:fixtures:loadを使うことによって共通化する方法です。

やり方

db/seed.rbにこう書く。

# db/seed.rb:
Rake::Task["db:fixtures:load"].execute

メリット

  • seedとfixturesがDRYになる。
  • テスト時のデータが画面から見える。
  • テストに使っているエッジケースのデータを普段から意識するようになる。

Q&A

Q. factory_girlの場合は?

A. factory_girlは素人にはおすすめできない。まずはRailsデフォルトのfixturesを使いこなしましょう。

Q. seed-fuは?

A. 窓から捨てましょう。

Q. 画像ファイルがseedに必要な場合は?

A. 良い質問です。こちらを参考にしてください。

db:fixtures:loadの後処理をする - komagataのブログ

よくある下記のようなアカウント編集ページをdeviseで作る場合。

https://gyazo.com/e7b9fc1bbc0df4ccc501d3d861e76e58

  • パスワードとパスワード(確認)を入力した場合はパスワードを更新。
  • パスワードを入力しなくても他の項目(emailなど)は更新可能。

こんな感じでresource.update_without_passwordを使い分ければOK。

# app/controllers/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
  protected
    def update_resource(resource, params)
      if params[:password].present? && params[:password_confirmation].present?
        resource.update_attributes(params)
      else
        resource.update_without_password(params)
      end
    end
end

簡単だけどdeviseのWikiには載ってないようなので。

現状、HTMLメールでsvgを使うのは辞めたほうが良さそうです。

https://gyazo.com/19e4e37f18ef7c7dce11c01925c9ecbf

なぜなら、Gmailはセキュリティのために画像などの外部リソースを専用のプロクシ的なもの経由で表示しますが、svgは表示させてくれないようです。

Hotmailなどの他の直接表示する系サービスは問題ないです。

とりあえず、pngを使うことで回避。

svgの方が軽さとか汎用性とかいろいろ便利なんで使いたいんですけどね。

db:fixtures:loadを使えばseed-fuなどを使った場合に起きるseedデータとテストデータの二度書きの手間無くなります。

しかし、paperclipで画像を保存してる時など、fixturesからは読み込めないものを保存している場合に対応できません。

僕は下記のようにして解決しています。

rakeタスクを書く

db:image:loadという画像をアップするtaskを書く。

# lib/tasks/fixtures.rake:

namespace :db do
  namespace :images do
    desc "Upload images."
    task load: :"db:fixtures:load" do
      User.all.each do |user|
        path = Rails.root.join("test", "fixtures", "files", "users", "avatars", "#{user.name}.jpg")
        user.update!(avatar: open(path)) if File.exist?(path)
      end
    end
  end
end

db:fixtures:loadの後に実行する

# lib/tasks/fixtures.rake:

...

Rake::Task["db:fixtures:load"].enhance do
  Rake::Task["db:images:load"].execute
end

これでrails db:fixtures:loadすればその後で画像も入ります。

PaperclipでGoogle Storageに画像を保存しているときに表示がクッソ遅い。

原因は表示するたびにファイルの存在確認のリクエストを出しているためで、1ファイルにつき200msぐらい遅くなってた。(30個の表示で計6秒遅くなってた)

対応方法は、fog_hostを設定しておけばリクエスト出さなくなるようで、普通の速度に戻りました。

config/initializers/paperclip.rb:

Paperclip::Attachment.default_options[:fog_host] = "http://#{ENV["GOOGLE_STORAGE_BUCKET_NAME"]}.storage.googleapis.com"

deviseのconfirmableモジュールを使うとデフォルトでemailを変更するときに再確認メールを送信する。

(これがサインアップ時のメールと同じ内容なので使い辛いというのは別の話)

設定でオフにできる。

config/initializers/devise.rb:

Devise.setup do |config|
  config.reconfirmable = false
end
class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :post

  alias_method :sender, :user

  def reciever
    post.user
  end
end

こうしておくとメール送るときにわかりやすい。

if comment.sender != comment.reciever
  NoticeMailer.came_comment(@comment).deliver_later
end

users_urlとかがメール内でも使える。

class ApplicationMailer < ActionMailer::Base
  include Rails.application.routes.url_helpers
end

sprocketsやturbolinksを使っていて全css, jsを読み込んでるとしても何だかんだ言って今どのページにいるのか知りたい場合が多いです。

thoughtbotのflutieに始まり色んなところで勝手にcontroller名とaction名をつなげたものを使っていますがそれをベースに動く機能が必要になったので、つなげるルールを明確化するためにgemにしました。

komagata/view_id: Identifier your view from controller and action.

抽象的な名前を取りすぎな気がしますが、とりあえず・・・。

名前のつなげ方でうすが、controllerとactionを--でつなぎます。

ネームスペースは-でつなぎます。

PostsController#index => posts-index
DeletedPostsController#show => deleted_posts--show
Admin::DeletedPostsController#create => admin-deleted_posts--create

いつも使う処理なのでgemにしました。

fixed_footer-rails | RubyGems.org | your community gem host

使い方

Gemfileに書きを追加。

gem "fixed_footer-rails"
$ bundler install

application.jsに書きを追加。

//= require fixed-footer

jsから呼び出す。例えばfooter.coffeeを作って下記のように書く。

$(document).on "turbolinks:load", ->
  new FixedFooter("your-own-footer-id")