Ruby on Rails 個人的メモ
APIアプリケーションを新規作成するときのオプション
rails --version
# Rails 7.2.1.1
rails new . \
--database=mysql \
--skip-docker \
--skip-action-mailer \
--skip-action-mailbox \
--skip-action-text \
--skip-active-job \
--skip-active-storage \
--skip-action-cable \
--skip-hotwire \
--skip-jbuilder \
--skip-test \
--skip-system-test \
--skip-dev-gems \
--skip-rubocop \
--skip-ci \
--api
--api
で--skip-asset-pipeline
と--skip-javascript
を指定したことと同じになるほか、APIアプリケーション用の設定を行ってくれる。
全てのオプションはrails new --help
で確認できる。
config/environments/production.rbにRuboCopをかけたときの話
require "active_support/core_ext/integer/time"
Rails.application.configure do
# 略
# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
# 略
end
にRuboCopをかけたら次のようになった
require "active_support/core_ext/integer/time"
Rails.application.configure do
# 略
# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new($stdout)
.tap { |logger| logger.formatter = Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
# 略
end
適用されたCopは
-
Style/GlobalStdStream
-
STDOUT
は$stdout
の初期値。$stdout == STDOUT
がtrueの場合はこの変更は安全。 - Rubyでは定数にも再代入でき、実際
STDOUT
に再代入しようとすると警告メッセージが出る。もし標準出力先を変えたいときは$stdout
にオブジェクトを代入すればよい。
-
- Layout/MultilineMethodCallIndentation
-
Style/RedundantConstantBase
-
左辺なしの
::
はObjectクラスで定義されている定数(トップレベルの定数)を確実に参照するために使う。 - 今回は
Module.nesting
が[]
だったので::
がなくてもトップレベルのLogger
が参照される。
-
左辺なしの
コントローラーの名前空間とルーティング
GET /api/todos
に対するコントローラーは
module Api
class TodosController < ApplicationController
def index
todos = Todo.all
render json: todos
end
end
end
Rails.application.routes.draw do
namespace :api do
resources :todos, only: :index
end
end
コントローラーのファイルはrails g controller api/todos
で作成できる。rails g controller
のヘルプには次のように書いてある。
To create a controller within a module, specify the controller name as a path like 'parent_module/controller_name'.
ルーティングのグループ化はRails Guideに詳しく書いてある。
save
とsave!
の違い
ActiveRecordのどちらもDBに保存するメソッドだが、save!
はバリデーションに失敗したときActiveRecord::RecordInvalid
の例外を発生させる。またbefore_save
などのコールバックが:abort
をスローしたときはActiveRecord::RecordNotSaved
の例外を発生させる。save
は例外を発生せずにfalse
を返す。成功したときはどちらもtrue
を返す。
create
とcreate!
、update
とupdate!
、destroy
とdestroy!
の違いも例外を発生させるかどうかの違いである。
テーブルのカラムにNOT NULL制約を追加するときのマイグレーション
class AddNotNullConstraintToTodoTitle < ActiveRecord::Migration[7.2]
def change
change_column_null(:todos, :title, false)
end
end
このファイルを追加し、rails db:migrate
を実行すればよい。rails db:rollback
するとchange_column_null(:todos, :title, true)
が実行され、NOT NULL制約が外れる。
HTTPレスポンスをパースするメソッド
RSpecで次のようなテストコードを書いた。
expect(JSON.parse(response.body)).to include('text')
これにRuboCopをかけたらRails/ResponseParsedBody
の警告が出た。
# bad JSON.parse(response.body) # bad Nokogiri::HTML.parse(response.body) # bad Nokogiri::HTML5.parse(response.body) # good response.parsed_body
parsed_body
メソッドはレスポンスのMIMEタイプに応じてレスポンスボディーをパースする。
RSpec導入手順
rspec-railsを入れる
bundle install
する。
group :development, :test do
gem 'rspec-rails', '~> 7.0.0'
end
その後rails generate rspec:install
を実行すると、.rspec, spec/rails_helper.rb, spec/spec_helper.rbが生成される。
factory_botを入れる
bundle install
する。
group :development, :test do
gem 'factory_bot_rails'
end
続いてspec/support/factory_bot.rbを作成して、以下の内容を記述し、spec/rails_helper.rb内でrequire
する。(spec/rails_helper.rbに直接記述してもよい。)
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
RuboCopの拡張機能を入れる
bundle install
する。
group :development do
gem 'rubocop-factory_bot', require: false
gem 'rubocop-rspec', require: false
gem 'rubocop-rspec_rails', require: false
end
.rubocop.ymlに以下を記述すると、ルールが適用されるようになる。
require:
- rubocop-factory_bot
- rubocop-rspec
- rubocop-rspec_rails
find
とfind_by
の違い
Active Recordのレコードが見つからなかったとき、find
はActiveRecord::RecordNotFound
の例外を発生させる。find_by
はnil
を返す。find_by!
は例外を発生させる。
attributes
メソッド
Active ModelのActiveModel::Attributes
モジュールのattributes
メソッドを用いると、インスタンスの属性のリストをハッシュで取得できる。