Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What are the problem?
@aiandrox

【Rails】俺のための初期設定 + Gem導入

rails newをするときに、随時設定をしたりGemを入れるのが面倒だったので、自分用にcloneするだけでいいリポジトリを作りました。
https://github.com/aiandrox/rails_app

ついでに作業をざっくりまとめました。

DockerやCircleCI用の設定はしていません。
実際に導入する際にはGitHubでバージョン指定や手順などを確認してください。

バージョン

  • Ruby 2.7.1
  • Rails 6.0.3.3
  • yarn 1.22.5

初期コマンドはrails new rails_app --skip-test-unit --database=mysqlです。

.gitignore/vendor/bundleを追加

/vendor/bundle

を追加する。

日本語化・時刻の設定

config/application.rb
...
module RailsApp
  class Application < Rails::Application
    ...
    # 言語・タイムゾーンを日本に設定
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local
  end
end
Gemfile
gem 'rails-i18n'
gem 'enum_help'

ついでにモデル用の日本語データも準備しておく。
en.ymlは不要なら消してしまってもいい。

config/locales/model.ja.yml
ja:
  activerecord:
    # User.model_name.human
    models:
      user: ユーザー
    # User.human_attributes_name(:name)
    attributes:
      id: ID
      created_at: 作成日時
      updated_at: 更新日時
      user:
        name: 名前

  enums:
    user:
      role:
        admin: 管理者
        general: 一般
        guest: ゲスト

リンク

デバッグ用のGem

binding.pryを使いたいので、byebugを削除してpryを入れる。

Gemfile
group :development, :test do
  # byebugは不要なら削除してよい
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # 以下3行を追加
  gem 'bullet'
  gem 'pry-byebug'
  gem 'pry-rails'
end

group :development do
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  # 以下2行を追加
  gem 'better_errors'
  gem 'binding_of_caller'
end
config/environments/development.rb
Rails.application.configure do
  ...
  # bulletの設定
  config.after_initialize do
    Bullet.enable = true
    Bullet.bullet_logger = true
    Bullet.console = true
    Bullet.rails_logger = true
    Bullet.add_footer = true
  end
end

better_errorsとbinding_of_callerによって、エラー画面がデフォルトのものから詳細なものに変えて、エラー画面でコンソール操作ができる。

pry-byebugとpry-railsによって、コードの途中にbinding.pryを書いておくと、そこで動作を止めてデバッグができる。

リンク

フォーマッター

Rails Best PracticesとRubocopの導入

Gemfile
group :development do
  # 以下4行を追加
  gem 'rails_best_practices'
  gem 'rubocop', require: false
  gem 'rubocop-performance', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-rspec', require: false
end

.rubocop.ymlでrubocop-performanceとrubocop-railsを読み込む。
また、カスタマイズする場合は.rubocop.ymlに記述を追加することでオーバーライドできる。

.rubocop.yml
# This file overrides https://github.com/bbatsov/rubocop/blob/master/config/default.yml

require:
  - rubocop-performance
  - rubocop-rails
  - rubocop-rspec

AllCops:
  Exclude:
    - 'tmp/**/*'
    - 'vendor/**/*'
    - 'db/**/*'
    - 'bin/**/*'
    - 'spec/**/*'
    - 'node_modules/**/*'
  DisplayCopNames: true

# 日本語でのコメントを許可
Style/AsciiComments:
  Enabled: false

# Admin::BaseControllerのような書き方を許可
Style/ClassAndModuleChildren:
  Enabled: false

# frozen_string_literal: trueはなくていい
Style/FrozenStringLiteralComment:
  Enabled: false

# each_key, value, transform_keys, valueを使用する
Style/HashEachMethods:
  Enabled: true
Style/HashTransformKeys:
  Enabled: true
Style/HashTransformValues:
  Enabled: true

# クラスにコメントを残さない
Style/Documentation:
  Enabled: false

# コントローラのメソッド名に「set_」「get_」を許可
Naming/AccessorMethodName:
  Exclude:
    - "app/controllers/**/*"

# 一行の長さは100字まで。コメントは制限しない
Metrics/LineLength:
  Max: 100
  IgnoredPatterns: ['\A#']
  Exclude:
    - "db/migrate/*.rb"

# メソッドの行数を20行までにする
Metrics/MethodLength:
  CountComments: false
  Max: 20

# ABC sizeは緩めにする
Metrics/AbcSize:
  Max: 30 # default 15

ついでにbundle exec rubocop -aで自動整形しておく。

ESlintの導入

$ yarn add -D eslint eslint-loader
config/webpack/loaders/eslint.js
module.exports = {
  test: /\.js$/,
  loader: "eslint-loader",
  enforce: "pre",
  options: {},
};
config/webpack/environment.js
const { environment } = require("@rails/webpacker");
const eslint = require("./loaders/eslint");  // 追加

environment.loaders.append("eslint", eslint);  // 追加
module.exports = environment;
$ yarn run eslint --init
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · commonjs
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JSON
Successfully created .eslintrc.json file in /Users/k_end/study/rails_app
✨  Done in 92.50s.

なんとなく読みながらオプションを選んでいくと.eslintrc.jsonが生成される。

.eslintrc.json
{
    "env": {
        "browser": true,
        "commonjs": true,
        "es2021": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": 12
    },
    "rules": {
    }
}

これでWebpackerのコンパイル時にESlintが走るようになる。bin/webpack-dev-serverで確認。
yarn run eslint --fixでESlint自動修正。

リンク

RSpec, FactoryBot

test/ディレクトリは削除する。

Gemfile
group :development, :test do
  # 以下2行を追加
  gem "rspec-rails"
  gem "factory_bot_rails"
end

bundle exec rails generate rspec:installでファイルが生成される。

spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'factory_bot'  # 追加
require 'rspec/rails'

Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }  # コメントアウト解除

begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!

  config.include FactoryBot::Syntax::Methods  # 追加
end

spec/spec_helper.rbconfig.filter_run_when_matching :focusをコメントアウト解除する。

.rspec
--require rails_helper
--format documentation
  • rails_helperでspec_helperを読み込んでいる
  • 素のRubyファイルをテストすることはまずない

という点から、--require rails_helperに変更しておく。
これにより、それぞれのspecファイルでrequire rails_helperを付けなくてもよくなる。

config/application.rb
module RailsApp
  class Application < Rails::Application
    ...
    # generateで作成するファイルの制限
    config.generators do |g|
      g.assets false
      g.skip_routes true
      g.helper false
      g.test_framework :rspec,
                       view_specs: false,
                       helper_specs: false,
                       routing_specs: false,
                       controller_specs: false,
                       request_specs: true,
                       model_spec: true,
                       fixtures: true
      g.fixture_replacement :factory_bot, dir: 'spec/factories'
    end
  end
end

ここのtrue or falseは必要に応じて変える。

リンク

seed_fu

Gemfile
gem 'seed-fu'

seed-fuが読み込むのはdb/fixtures/配下のファイルなので、fixtures/ディレクトリを作成しておく。

リンク

foreman

Gemfile
group :development do
  gem 'foreman'  # 追加
end
Procfile
rails: rails s --port=3000
webpacker: bin/webpack-dev-server
$ bundle exec foreman check
valid procfile detected (rails, webpacker)
$ bundle exec foreman start

リンク

slim

Gemfile
gem 'slim-rails'
gem 'html2slim'

bundle exec erb2slim app/views app/views -dで置換する。ERB 2 SLIMを使うのもあり。
置換したらhtml2slimは不要なので削除する。

config/application.rb
module RailsApp
  class Application < Rails::Application
    ...
    config.generators do |g|
      ...
      g.template_engine = :slim  # 追加
    end
  end
end

リンク

annotate

Gemfile
group :development do
  gem 'annotate'
end

bundle exec rails g annotate:installを実行する。

lib/tasks/auto_annotate_models.rake
# NOTE: only doing this in development as some production environments (Heroku)
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
# NOTE: to have a dev-mode tool do its thing in production.
if Rails.env.development?
  require 'annotate'
  task set_annotation_options: :environment do
    # You can override any of these by setting an environment variable of the
    # same name.
    Annotate.set_defaults(
      'active_admin' => 'false',
      'additional_file_patterns' => [],
      'routes' => 'false',
      'models' => 'true',
      'position_in_routes' => 'before',
      'position_in_class' => 'before',
      'position_in_test' => 'before',
      'position_in_fixture' => 'before',
      'position_in_factory' => 'before',
      'position_in_serializer' => 'before',
      'show_foreign_keys' => 'true',
      'show_complete_foreign_keys' => 'false',
      'show_indexes' => 'true',
      'simple_indexes' => 'false',
      'model_dir' => 'app/models',
      'root_dir' => '',
      'include_version' => 'false',
      'require' => '',
      'exclude_tests' => 'false',
      'exclude_fixtures' => 'false',
      'exclude_factories' => 'false',
      'exclude_serializers' => 'false',
      'exclude_scaffolds' => 'true',
      'exclude_controllers' => 'true',
      'exclude_helpers' => 'true',
      'exclude_sti_subclasses' => 'false',
      'ignore_model_sub_dir' => 'false',
      'ignore_columns' => nil,
      'ignore_routes' => nil,
      'ignore_unknown_models' => 'false',
      'hide_limit_column_types' => 'integer,bigint,boolean',
      'hide_default_column_types' => 'json,jsonb,hstore',
      'skip_on_db_migrate' => 'false',
      'format_bare' => 'true',
      'format_rdoc' => 'false',
      'format_yard' => 'false',
      'format_markdown' => 'false',
      'sort' => 'false',
      'force' => 'false',
      'frozen' => 'false',
      'classified_sort' => 'true',
      'trace' => 'false',
      'wrapper_open' => nil,
      'wrapper_close' => nil,
      'with_comment' => 'true'
    )
  end

  Annotate.load_tasks
end

リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What are the problem?