Ruby on Rails Muster für Klasse Standardwerte einstellen und damit eine Überschreibung auf Subklassen

StackOverflow https://stackoverflow.com/questions/1072767

Frage

Grundsätzlich mag ich eine einfache Rails-Erweiterung implementieren, um die Schwere der Methoden in meinem Controller zu definieren, so dass ich den Gebrauch von ihnen in geeigneter Weise einschränken. Zum Beispiel würde ich die Standard geruhsamen Aktionen wie so in einer abstrakten Superklasse definieren:

view_methods :index, :show
edit_methods :new, :create, :edit, :update
destroy_methods :destroy

Ich würde dann nach unten in einem nicht-abstrakten Controller Aufruf:

edit_methods :sort

in der Sortiermethode auf diesem speziellen Controller hinzuzufügen, als eine Editlevel Methode zu sein.

Ich konnte dann eine before_filter verwenden, um die Ebene der Maßnahme überprüfen zur Zeit durchgeführt wird, und breche es, wenn meine Logik bestimmt, dass der aktuelle Benutzer kann es nicht tun.

Das Problem ist, ich habe Probleme, herauszufinden, wie diese Art von Struktur einzurichten. Ich habe so etwas wie dies versucht, so weit:

class ApplicationController

  @@view_methods = Array.new
  @@edit_methods = Array.new
  @@destroy_methods = Array.new

  def self.view_methods(*view_methods)
    class_variable_set(:@@view_methods, class_variable_get(:@@view_methods) << view_methods.to_a)
  end

  def self.edit_methods(*edit_methods)
    class_variable_set(:@@edit_methods, self.class_variable_get(:@@edit_methods) << edit_methods.to_a)
  end

  def self.destroy_methods(*destroy_methods)
    @@destroy_methods << destroy_methods.to_a
  end

  def self.testing
    return @@edit_methods
  end


  view_methods :index, :show
  edit_methods :new, :create, :edit, :update
  destroy_methods :destroy

end

Die drei oben genannten Methoden sind unterschiedlich absichtlich, nur um Ihnen zu zeigen, was ich versucht habe. Der dritte funktioniert, aber liefert die gleichen Ergebnisse, egal was ich Controller testen. Wahrscheinlich, weil die Klassenvariablen in der Applikationssteuerung gespeichert sind, werden global so geändert wird.

Jede Hilfe wäre sehr geschätzt.

War es hilfreich?

Lösung

Das Problem ist, dass Ihre Klassenvariablen vererbt werden, sondern auf die gleiche Instanz von Array. Wenn Sie ein Update, wird es auch auf allen Klassen aktualisiert werden, die die Array vererbt.

ActiveSupport bietet eine Lösung rel="nofollow für dieses Problem, indem die Class Klasse mit mehreren Methoden erstreckt zu definieren vererbbare Klasse Attribute . Sie werden überall intern in Rails verwendet. Ein Beispiel:

class ApplicationController
  class_inheritable_array :view_method_list
  self.view_method_list = []

  def self.view_methods(*view_methods)
    self.view_method_list = view_methods  # view_methods are added
  end

  view_methods :index, :show
end

Jetzt können Sie die Standardwerte in ApplicationController gesetzt und überschreiben sie später.

class MyController < ApplicationController
  view_method :my_method
end

ApplicationController.view_method_list #=> [:index, :show]
MyController.view_method_list #=> [:index, :show, :my_method]

Sie können sogar die view_method_list als Instanz Methode auf dem Controller verwenden (z MyController.new.view_method_list).

In Ihrem Beispiel Sie nicht definierten eine Möglichkeit, Methoden aus den Listen zu entfernen, aber die Idee ist so etwas wie die folgende tun (im Fall müssen Sie es):

# given the code above...
class MyController
  self.view_method_list.delete :show
end
MyController.view_method_list #=> [:index, :my_method]

Andere Tipps

Ich drehte ihn in ein Plugin wie folgt:

module ThreatLevel

  def self.included(base)
    base.send :extend, ClassMethods
  end

  module ClassMethods
    def roger_that!
      class_inheritable_array :view_method_list, :edit_method_list, :destroy_method_list

      self.view_method_list = Array.new
      self.edit_method_list = Array.new
      self.destroy_method_list = Array.new

      def self.view_methods(*view_methods)
        self.view_method_list = view_methods
      end

      def self.edit_methods(*edit_methods)
        self.edit_method_list = edit_methods
      end

      def self.destroy_methods(*destroy_methods)
        self.destroy_method_list = destroy_methods
      end

      view_methods :index, :show
      edit_methods :new, :create, :edit, :update
      destroy_methods :destroy
    end
  end
end

ActionController::Base.send :include, ThreatLevel

Beim roger_that! auf dem super_controller, wo Sie es wollen Effekt funktioniert der Trick nehmen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top