ずみーBlog

元クラゲ研究者(見習い)の92年生まれがエンジニアを目指しながら日々寄り道するブログです。

【Ruby】sendメソッドとattr_accessorで属性を動的に読み書きする

おはようございます。ずみーです。 Rubyでメソッドの呼び出しはインスタンス名.メソッド名ですが、インスタンス名.メソッド名の部分をパラメータにして動的に呼び出したいことってありますよね。

結論:sendメソッドで実現可能

使い方はこんな感じです。

#インスタンスobjとメソッド名methodを受け取ってメソッドを呼び出す関数
def execute_method(obj, method)
  obj.send(method)
end

また、インスタンスobjattr_accesorで属性が定義してある場合、属性への値の書き込みは以下のようにやります。

#クラス
class ClassName
  attr_accessor :attr1, :attr2
end

#インスタンスobjと属性名attrと値valを受け取って、属性値を設定する関数
def set_attr(obj, attr, val)
  obj.send("#{attr}=", val)
end

#呼び出しかた
instance = new ClassName
set_attr(instance, "attr1", "val1")
set_attr(instance, "attr2", "val2")

どこで使う?

私はFormオブジェクトパターンでの単体テストで使いました。

続きを読む

【ポイント:擬似モデル】Formオブジェクトパターンを理解する

Railsデザインパターンの一つであるFormオブジェクトパターンを使って、フォームから一度の送信で複数のテーブルに安全に情報を送る方法について学びました。

フォームから複数モデルの情報を送る際の問題点

form_withメソッドに渡しているのは単一のモデルのインスタンスなので、他のモデルクラスがもつ属性の情報が送れません。

Formオブジェクトパターンを使わない場合の解決法

form_with:modelの指定をやめ、paramsに送信した全ての値が入るようにします。

続きを読む

数値をカンマ付きの金額表示にしたい

ごく短いメモです。 Rubyには:delimited:currencyという便利なメソッド(というかto_sのオプション?)があり、特に引数を指定しなくても金額表示の時のカンマ区切りをよしなにやってくれます。

1000.to_s(:delimited)
# => 1,000

Railsのビューではさらに便利なヘルパーが用意されています

続きを読む

【RSpec】モデル単体テストで、全カラムに対して.eachで同じ操作を実行したい

Rails単体テスト書いてます。 例えばpresence: trueみたいな、たくさんのカラムに適用されているバリデーションって、一つ一つ書くのがめんどくさいですよね。 全カラムを配列で取得し、each文で回して、presence: trueバリデーションを一括でテストしてみました。

続きを読む

Spec 結合テストコードをまとめる

同じ処理を繰り返している箇所 →サポートモジュールを使って一つのメソッドにまとめる

ex)ログイン動作 ←何度もやってる

サポートモジュールの作成

spec/support/sign_in_support.rb

module SignInSupport
  def sign_in(user)
    visit new_user_session_path
    fill_in 'Email', with: user.email
    fill_in 'Password', with: user.password
    find('input[name="commit"]').click
    expect(current_path).to eq root_path
  end
end
続きを読む

RSpec自動テスト時に画像を添付する

単体テストの時

単体テスト時はrack-testというGemを使うことで、添付される側のレコードに対してファイル添付できます。

FactoryBotと一緒に使用した例

FactoryBot.define do
  factory :item do
    association :user
    name                   { Faker::Lorem.word }
    #省略
    image                  { Rack::Test::UploadedFile.new(File.join(Rails.root, 'public/images/test_image.jpg')) }
  end
end
続きを読む