10

私はRoRに単純なモデルを持っており、サイトにすべての人が入るようにしておきたいと思います。ただし、ユーザーが[削除]をクリックした場合に一部のコンテンツを非表示にできるようにもしたいと思います。

そこで、モデルに「displayed」というbolean属性を追加しました。

ベストプラクティススタイルの方法は何でしょうか。

私はコントローラーを次のようなものに変更する必要があると思います:

def destroy
 @point = Point.find(params[:id])
 @point.displayed = false
 @point.save

respond_to do |format|
  format.html { redirect_to points_url }
  format.json { head :no_content }
end

しかし、それがきれいかどうかはわかりません。それを行うための最良の方法は何でしょうか。

ご想像のとおり、私はRoRに精通していません。コードの塊をいただければ幸いです。

ありがとうございました

4

5 に答える 5

13

(gemを使用するのではなく)自分で実装します。それは最初に思われるよりもはるかに簡単であり、方法の意味を変えるdestroy他のどの宝石よりも複雑ではありません。これは悪い考えです。

宝石自体の使用が複雑だと言っているのではありません-destroyメソッドの意味を変更することで、Railsの世界の人々が当然と思っているものの意味を変更していると言っています-destroyそのレコードを呼び出すと、コールバックを介してチェーンされてdestroyいる場合は、依存オブジェクトに対しても呼び出される可能性がありdependent: destroyます。

の意味を変えることdestroyも悪いことです。なぜなら、「設定より規約」の世界では、規約を台無しにすると、基本的にRailsコードの「自動魔法」を破ってしまうからです。Railsコードの一部を読んでいて、特定の仮定が一般的に適用されることを知っているので、当然のことと思っているすべてのもの-それらは窓の外に出ます。明らかではない方法でこれらの仮定を変更すると、それが原因でバグが発生することはほぼ確実です。

誤解しないでください。仮定を確認するためのコードを実際に読むことほど良いことはありませんが、コミュニティとして、特定のことについて話し、一般的に特定の方法で行動させることができるのも良いことです。

次のことを考慮してください。

  • destroyRailsには、コントローラーにアクションを実装する必要があると言っているものは何もないので、そうしないでください。これは標準的なアクションの1つですが、必須ではありません。
  • アクションを使用して、ブール属性(または同様の名前の属性)updateを設定およびクリアしますarchived
  • 私はacts_as_paranoidgemを使用しましたが、モデルにスコープを追加する必要がある場合(gemが提供するスコープ以外)、デフォルトの「アーカイブされたレコードを非表示」をオフにして、モデルをハックする必要があります。 「スコープ、そしてあなたがそれに遭遇すると、それはほとんどすぐにその価値を失います。その上、そのgemはそれ自体ではほとんど何もしません。また、その機能は自分で簡単に作成できます(つまり、gem自体をインストールするよりもほとんど作業が必要です)。そのため、その観点から使用してもメリットはありません。
  • 前に述べたように、メソッドまたはアクションをオーバーライドすると、オブジェクトdestroyを呼び出すことの意味に関するRails(およびActiveRecord)の規則に違反するため、お勧めできません。destroyこれを行う宝石(acts_as_paranoidたとえば)もその慣習を破っています。あなたは自分自身や他の誰かを混乱させることになります。なぜなら、それdestroyが何を意味するのかを単に意味しないからです。これにより、コードが明確になるのではなく、混乱が生じます。これを行わないでください-後で支払います。
  • データを破壊する可能性のある理論上の将来の開発者から保護しているためにソフト削除gemを使用したい場合は、そのための最善の解決策は、それらの人々を雇ったり協力したりしないことです。経験の浅い人は、間違いを防ぐための宝石ではなく、メンターシップが必要です。
  • 本当に、絶対に、特定のモデルのレコードを破棄しないようにする必要がある場合(単にアーカイブできることに加えて)、before_destroyコールバックを使用してfalseを返すだけです。これにより、delete使用されます(とにかくdestroyと同じではありません)。また、コールバックを設定するdestroyと、(a)意味を変えずに機能しない理由が非常に明確になり、(b)破壊できないことを確認するためのテストを簡単に作成できます。これは、将来、誤ってそのコールバックを削除したり、そのモデルを破壊可能にする何かをしたりした場合、テストが失敗し、状況を警告することを意味します。
于 2013-02-06T01:27:08.403 に答える
11

このようなもの:

class Point < ActiveRecord::Base

  def archive        
    update_attribute!(:displayed, false)
  end 

end

次に、@point.archive通常はを呼び出すコントローラーの破棄アクションを呼び出します@point.destroydefault_scopeアーカイブされたポイントを明示的にクエリするまで非表示にするを作成することもできます。デフォルトのスコープの適用に関するRoRガイドを参照してください。

編集:以下のnormalocity&loganのコメントに従って私の答えを更新しました。

于 2013-02-05T23:20:17.590 に答える
2

acts_as_archivegemを見てください。ソフト削除をシームレスに実行します。

于 2013-02-05T23:16:00.960 に答える
2

あなたの解決策は良いですが、acts_as_paranoidgemを使ってそれを管理することができます。

于 2013-02-05T23:16:16.817 に答える
0

このシナリオでは、新しいブールフラグを追加する代わりに、deleted_at:datetime列を追加する方が適切です。

@point = Point.find(params[:id])
@point.touch(:deleted_at)
...

じゃあ後で

Point.where(deleted_at: nil) # these are NOT hidden
Point.where.not(deleted_at: nil) # these are hidden
于 2019-04-26T16:57:55.180 に答える