QA@IT

モデルのクラス内で、新規登録・更新時に列(属性?)の値を取得する方法

2905 PV

お世話になっております。

環境

  • Ruby 2.0.0
  • Rails 4.0.0

質問内容

あるモデル内で、コントローラごとにモデルのvalidatesを設定したいというのが目的なのですが、
その際に、モデル内で列の値を参照し、
列「type_id」が1の場合には、特定のvalidatesを実行しないようにしたいのです。

このモデルを通してのデータ登録を、いくつかのコントローラから行っており、
そのコントローラ毎に、type_idが異なります。新規登録時・更新時に、type_idを参照して、
validatesの実行を制御できますか?

また、下記のモデルのコードで理解が足りないので細かな質問なのですが、
before_saveにおいてname.downcase!で列nameの値を制御できているのですが、
nameの値を取得するにはどのようにするのでしょうか?

よろしくお願いいたします。

model Command

class Command < ActiveRecord::Base
  before_save { name.downcase!; name.strip! }
  belongs_to :user
  belongs_to :category

  #validates :name, presence: true, length: { maximum: 20 }
  validates :usage, length: { maximum: 140 }
  validates :title, length: { maximum: 140 }

end

Commandsスキーマの構造

create_table "tests", force: true do |t|
    t.integer  "user_id"
    t.integer  "category_id",               default: 0
    t.string   "name",          limit: 20
    t.string   "title",         limit: 140
    t.string   "usage",         limit: 140
    t.text     "body"
    t.integer  "type_id",             default: 0
    t.datetime "created_at"
    t.datetime "updated_at"
  end

回答

:ifオプションを使うと簡単にできます。

質問を理解できているか自信がないのですが、↑のページの「コールバックの設定」のサンプルコードを参照して、見よう見まねで書いてみるとうまくいかないでしょうか。
self.nameとかで入力されたnameの値にはアクセスできると思いますが。。。

リンクばかりですいません。
Ruby2.0/Rails4.0で変わってたりしたらごめんなさい。

編集 履歴 (0)
  • Oakbow様 ありがとうございます!解決いたしました。
    しかし、疑問がまだあります。
    validatesの上で「logger.info(self.name)」とすると、モデル名が出力され、他のスキーマ属性では no method errorとなります。validatesのif文字列内と、モデルの中では扱いがことなるのでしょうか。ActiveRecordを学習した方がよいということでしょうか。
    -

意図する動作は実現できたのですが、Okabow様の回答のコメントに書きましたように、
以下の場合に、logger.infoでのself.type_idでundefined methodエラーが出ます。
また、self.nameをログ出力すると、モデル名が表示されます。

記述する場所により異なるのはなぜでしょうか?ActiveRecordを理解する必要があるということでしょうか。

  logger.info("ここで")
  logger.info(self.type_id)
  validates :name, presence: true, length: { maximum: 20 }, if: Proc.new { self.type_id == COMMAND_TYPE_ID }
  validates :usage, length: { maximum: 140 }
  validates :title, length: { maximum: 140 }
編集 履歴 (0)
  • なぜそうなるかはRubyのクラスの仕組みをしっかり理解する必要があるので省略しますが、ユーザ入力の中身を確認したいのなら、コントローラに書くといいですよ。 -
  • ありがとうございます。やっぱりはっきりと違いがあるみたいですね。Rubyの基礎から勉強やり直します。メソッド内とそれ以外の違いかな。。ありがとうございました! -
ウォッチ

この質問への回答やコメントをメールでお知らせします。