0

対処方法についてアドバイスが欲しかっto_parampermalinks

基本的にはこうなります。

  • 新しい会社を作る
  • その後、会社はパラメータ化され、データベースに:nameとして保存されます:permalink
  • 既存の会社を更新すると、:permalink
  • 更新されたユーザー:permalinkが一意であることを確認するための検証があります

私が抱えている問題は、会社を既存の:permalinkものに更新するときに発生しています。一意性の検証はうまく機能しますがparams[:id]、既存のパーマリンクをリセットして使用する代わりに、無効なパーマリンクに変更しますparams[:id]

を別のものに編集しようとすると、既存の会社 (会社) を編集していると見なされるためpermalink、フラッシュ検証エラーが発生します。を使用してからの変更が URL に反映されます"Name already taken":permalinkpermalinkcompanies_controller.rb@company = Company.find_by_permalink[:id])

この問題を処理する最善の方法を知りたいですか?

class Companies < ActiveRecord::Base
  before_create :set_permalink
  before_update :update_permalink

  attr_accessible :name, :permalink

  validates :name, :permalink, uniqueness: { message: 'already taken' }

  def to_param
    permalink
  end

  private

  def set_permalink_url
    self.permalink = name.parameterize
  end

  def update_permalink_url
    self.permalink = permalink.parameterize
  end


end

私があまり意味を成していない場合はお詫び申し上げます。

前もって感謝します。

4

1 に答える 1

0

コールバックでこれを処理しようとすることができafter_rollbackます。

 after_rollback :restore_permalink

 def restore_permalink
   self.permalink = permalink_was if permalink_changed?
 end

これがどのように機能するかです: Rails のすべての更新 / 破棄はトランザクションにラップされます。保存が失敗した場合、トランザクションはロールバックし、コールバックをトリガーします。permalink_wasコールバックは、レコードがロードされてから変更された場合、古い値 ( ) を復元します。

詳細については、 ActiveModel::DirtyおよびActiveRecord::Transactionsを参照してください。

編集

一方、別の解決策(テストされていない)があるかもしれません-次のようにアクセサーを定義するだけです:

 def permalink=( value )
   permalink_will_change! unless @permalink == value
   @permalink = value
 end

このように、新しい値が古い値と同一である場合、パーマリンクはダーティとしてマークされないため、AR は列を更新しようとしません。

説明:

それが実装されたレールのバージョンはわかりませんが(比較的最近のものです)、「汚れ」がどのように機能するかは次のとおりです。

  • 「標準」(自動生成された)属性セッター は、基本#{your_attribute}_will_change!的に、関連するインスタンス変数を設定する前に呼び出します(以前とまったく同じ値を設定した場合でも)
  • を呼び出すとsave、ActiveRecords は変更された (「ダーティ」) 属性を探し、これらの属性のみを使用して SQL UPDATE クエリを構築します (主にパフォーマンス上の理由から)。
  • したがって、パーマリンクが変更されていないときにクエリに表示されるのを避けたい場合は、標準のセッターをオーバーライドするか、一括割り当てを避けpermalinkて、変更された場合にのみ設定する必要があると思います
于 2012-11-10T17:27:53.897 に答える