0

以下を考慮して

:company has_many :issues  #ticket tracking example

会社内のすべてのユーザーが /issues/:id にアクセスできるようにルーティングしたいと思います (デフォルトの id 列を使用する場合、これは十分に単純です)。

ただし、代わりに会社に固有の問題 ID を持ちたいと思います (そのため、各会社には固有ではない (そして内部 ID を使用しない) 独自の問題 1、2、3 などがあります)。

その会社IDのIssueControllerの作成および更新アクションで、データベースの最後の番号に基づいてIDを計算するよりも良い方法はありますか? (ここでは、会社ごとに複数のレコードが更新/作成されている場合の競合状態に関するさまざまな問題を考えることができます)。

前もって感謝します!

4

2 に答える 2

1

issue_idハンドリングをモデルレベルまで下げます。before_validation コールバックを使用して、issue_id. これだけでは、save呼び出しがトランザクションにラップされていても、競合状態を防ぐことはできません。@ PinnyM で提案されているよう[ :company_id, :issue_id ]に、インデックス/一意の制約をテーブルに追加して、カップルの一意性をさらに確保する必要があります。issuesだから、このようなもの

class Issue < ActiveRecord::Base
  attr_accessible :company_id, :issue_id
  belongs_to :company
  before_validation :set_issue_id

  private
    def set_issue_id
      self.issue_id = self.company.issues.size + 1
    end
end

class Company < ActiveRecord::Base
  has_many :issues
end

および移行内:

add_index :issues, [:issue_id, :company_id], :unique => true

そして、あなたが言ったように、コントローラーで正しい問題をつかむことができます:

@issue = Issue.where(company_id: current_user.company.id, issue_id: params[:id])

これは、実際に発生した場合に制約違反の例外から回復する方法を提供しないことに注意してください。これを処理する方法に関する提案については、@ PinnyM の回答を参照してください。

お役に立てれば。

于 2013-02-18T17:50:21.103 に答える
1

最初に質問を誤解した後、もう一度試してみます。

company_id に固有の問題「カウンター」(ID をシミュレートするため) を作成する方法を探しています。@deivid は正しい方向に進んでいましたがissues.count、会社が一度に複数のリクエストを決して行わないことを保証できる場合にのみ、に頼ることができます。これは一般的に当てはまりますが、保証されていないため、このカウンターの背後にあるコア ロジックとして単独で使用しないでください。

テーブルに一意の制約/インデックスを追加する必要がありissuesます-これにより、カウンターが複製できないことが保証されます。

add_index :issues, [:issue_id, :company_id], :unique => true

モデルに制約を追加する:uniquenessと、競合状態のウィンドウが小さくなり、問題が多少軽減されるだけですが、一意性を完全に保証することはできません。

DB で制約違反が発生した場合、ActiveRecord はトランザクション内でそれを回復できないことに注意してください。をレスキューActiveRecord::RecordNotUniqueし、再作成issue(またはissue_id新しい を使用して再生成count) し、再度保存することができます。

于 2013-02-18T18:31:41.293 に答える