質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

4291閲覧

railsのモデルのカスタムvalidationをメソッドの値に対して行う

ayu

総合スコア212

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2016/06/19 09:32

編集2016/06/20 12:55

こんにちは。

validationで外部からの値を存在することに対してのvalidationを作ることはできますか?

画像を保存する際のurlを入力paramsで受け取っているのですが、そのparamsが空白の場合はエラーで返すようにしたいのです。

現状のコードです。

app/model/image.rb

ruby

1class Image < ActiveRecord::Base 2 def remote_url(url)←ここのurlをparamsで受け取っています。 3 return errors.add(:image, 'URLを入力してください') if url.blank? ←応急処理 4 self.image = URI.parse(url) 5 end 6end

上記のコードで応急処理がない場合のurlがnilの場合です。

ruby

1Failure/Error: self.image = URI.parse(url) 2 3TypeError: 4 no implicit conversion of URI::Generic into String

rspecのコードです。

ruby

1RSpec.describe Image, type: :model do 2 describe 'validation' do 3 let(:image) { build(:image) } 4 it 'remote_urlは空白ではない' do 5 url = '' 6 image.remote_url(url) 7 expect(image).not_to be_valid 8 end 9 end 10end 11 1213Failure/Error: expect(image).not_to be_valid 14 expected #<Image id: nil, imageable_id: 1, imageable_type: "MyString", created_at: nil, updated_at: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil> not to be valid

カスタムvalidationでこのurlの存在がなければ、エラーにしたいのです。

ただ、メソッドの値に対してvalidationを書くことはできるのでしょうか?

あくまでもurlは外部の値から来るものなので、この値に関してのvalidationの方法が思いつかなかったです。

カラムの値なら、やりようはあると思っております。

現状のコードはモデルのメソッドの中にvalidation要素も入っていて、違和感を感じております。

希望するものは、応急処理を別メソッドに移したいです。

何かいい方法はありますでしょうか?m(_ _)m

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

rails4であれば,モデル内に
include ActiveModel::Model
と記述すれば,validatesメソッドが使えるようになるので,

ruby

1class A 2 3include ActiveModel::Model 4 5validate :some_validation 6 7def some_validation 8 任意のvalidation 9 if (invalidである条件) 10 errors.add(~任意のメッセージ) 11 end 12end 13 14def some_method 15 16 return false unless valid? 17 ...正常なパラメータなら続きを実行 18end 19 20end

クラス内や,コントローラーからインスタンス経由でvalid?メソッドを呼び出すようにすると,validateメソッドで登録したメソッドを実行出来ます。
この登録したメソッドの中でerrors.addを実行するとvalid?methodはfalseを返すようになるので,これを用いて以上のように書くことができます。

因みにActiveRecordを継承しているモデルはActiveModel::Modelを内包しているのでvalidateメソッド全般が使えるので同様の処理ができます。また,ActiveRecordはCRUDメソッド実行時にvalidationに登録してあるメソッドを全て実行してくれます。

こちらの記事が参考になるかと思います。

加えて複数のモデルが関連しあってparamsを共有して複数のモデルを保存したい場合,validationしてモデルに渡す際にvalidationを担当するformオブジェクトと,保存のロジック(カスケード保存の制御など)を担当するServiceオブジェクト,実際にパラメータを受け取るModelに分けて,設計するなどのデザインパターンもあるので興味があれば調べてみてください。
この場合は,formオブジェクトでparamsのvalidationを担当させるので,ActiveModel(データベース保存が必須でない時にはこちらのモジュールを使う方が推奨です)を使うことになります。

投稿2016/06/23 02:24

編集2016/06/23 04:26
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ayu

2016/06/23 14:14

ああ、保存するカラムの`image`に新しいvalidationを付け加えればいいんですね! スッキリしました。 >加えて複数のモデルが関連しあってparamsを共有して複数のモデルを保存したい場合,validationしてモデルに渡す際にvalidationを担当するformオブジェクトと,保存のロジック(カスケード保存の制御など)を担当するServiceオブジェクト,実際にパラメータを受け取るModelに分けて,設計するなどのデザインパターンもあるので興味があれば調べてみてください。 時間があるときに調べてみます。 詳しい説明、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問