[RUBY] Wenn es einen Statusübergang gibt, erstellen wir eine Statusklasse

Wenn Daten vorhanden sind, die in einen Status übergehen, tritt diese Art von Code häufig auf.

erb:view.html.erb


<%#Es scheint, dass keine Genehmigung erteilt werden kann, wenn der Status des Berichts 1 oder 2 ist, aber wie sind die Status 1 und 2?%>
<%= button_tag('Die Genehmigung', disabled: (report.state == 1 || report.state == 2)) %>

reports_controller.rb


def accept
  report = Report.find(params[:id])
  #Für die Behandlung ist dieselbe bedingte Anweisung wie view erforderlich!
  if report.state == 1 || report.state == 2
    flash[:error] = 'Kann nicht genehmigen'
    redirect_to root_url
  end
  report.state = 3 #Genehmigungswert!
  report.save!
end

Wenn Sie eine Konstante verwenden, verbessert sich diese ein wenig, aber ...

erb:view.html.erb


<%= button_tag('Die Genehmigung', disabled: (report.state == Report::STATE_DRAFT || report.state == Report::STATE_TRASH)) %>

reports_controller.rb


def accept
  report = Report.find(params[:id])
  #Immerhin ist die gleiche bedingte Anweisung wie view erforderlich!
  if report.state == Report::STATE_DRAFT || report.state == Report::STATE_TRASH
    flash[:error] = 'Kann nicht genehmigen'
    redirect_to root_url
  end
  report.state = Report::STATE_APPROBAL
  report.save!
end

report.rb


class Report < ApplicationRecord
  #Wenn viele Spalten Konstanten erfordern, sind viele Konstanten erforderlich.
  #Außerdem ist der Anwendungsbereich zu groß und es ist schwierig, den Zweck zu erkennen.
  STATE_DRAFT = 1
  STATE_TRASH = 2
  STATE_APPROBAL = 3
end

Es gibt eine Möglichkeit, ActiveRecord :: Enum anstelle einer Konstante zu verwenden, aber es löst nicht die Notwendigkeit derselben bedingten Anweisung an verschiedenen Stellen ... Dies kann durch Hinzufügen einer Methode zum ActiveRecord-Modell gelöst werden.

report.rb


class Report < ApplicationRecord
  STATE_DRAFT = 1
  STATE_TRASH = 2
  STATE_APPROBAL = 3

  def can_accept?
    state != STATE_DRAFT && state != STATE_TRASH
  end
end

Aber das ist der Weg zum Fat Model ... Damit ...

Erstellen wir eine Klasse, die Statusübergänge verwaltet

Vermeiden Sie die Fettmodellierung von ActiveRecord-Modellen und erstellen Sie Zustandsübergangsklassen mit klaren Verantwortlichkeiten. Es wäre schön, wenn die bedingte Anweisung eine Statusänderungsmethode namens "report_state.to_approval" mit dem Gefühl "report_state.approval_in_next" hätte? "[^ 1](kann sie sich im genehmigten Zustand befinden).

[^ 1]: Der Methodenname soll "Gibt es eine Genehmigung im nächsten Bundesstaat?" Sein. Da es sich jedoch um einen englischen, verdammt verschiedenen Fisch handelt, gibt es möglicherweise andere gute Methodennamen.

reports_controller.rb


def accept
  report = Report.find(params[:id])
  report_state = report.state_object
  #Sauber
  unless report_state.approval_in_next?
    flash[:error] = 'Kann nicht genehmigen'
    redirect_to root_url
  end
  #Dies ist ein einfaches Beispiel mit nur einer Spalte, aber selbst wenn die Verarbeitung des Zustandsübergangs kompliziert ist, zu_*Kann in der Methode versteckt werden!
  new_report_state = report_state.to_approval
  report.state = new_report_state.state
  report.save!
end

report.rb


class Report < ApplicationRecord
  # state_object=Es kann zweckmäßig sein, eine Methode zu erstellen
  def state_object
    ReportState.new(state)
  end
end

Die eigentliche ReportState-Klasse sieht folgendermaßen aus.

report_state.rb


class ReportState
  attr_accessor :state
  #Verschieben Sie Konstanten aus der Report-Klasse. Es passt immer besser
  DRAFT = 1
  TRASH = 2
  APPROBAL = 3

  def initialize(state)
    self.state = state
  end

  def approval_in_next?
    state != DRAFT && state != TRASH
  end

  def to_approval
    raise 'Illegaler Staatsübergang!' unless approval_in_next?

    self.class.new(APPROBAL)
  end
end

Selbst wenn die Bedingungen, die genehmigt werden können, kompliziert werden oder der Prozess des Zustandsübergangs in den Genehmigungsstatus kompliziert wird, müssen Sie hier nur noch Änderungen vornehmen!


Dieser Eintrag ist für Zustandsübergangsdiagramm, Zustandsübergangstabelle in Anforderungsanalyse-gesteuertes Design. #% E7% 8A% B6% E6% 85% 8B% E9% 81% B7% E7% A7% BB% E5% 9B% B3% E7% 8A% B6% E6% 85% 8B% E9% 81% B7% E7% A7% BB% E8% A1% A8) wurde neu organisiert und in allgemeine Inhalte umgeschrieben. Es ist eine lange Geschichte, aber es ist eine Geschichte über DDD-ähnliche Dinge in Rails.

Recommended Posts

Wenn es einen Statusübergang gibt, erstellen wir eine Statusklasse
Wenn Sie komplizierte Berechnungen haben, erstellen wir eine CalcRule-Klasse
Was ist eine Wrapper-Klasse?
[Rails DM] Erstellen wir eine Benachrichtigungsfunktion, wenn DM gesendet wird!
Erstellen Sie abschließend eine Methode, um festzustellen, ob ein Zeichen vorhanden ist
Resultsets next () ist keine "Methode, um festzustellen, ob es ein ResultSet next gibt".
[Java] Bedingte Verzweigung ist eine if-Anweisung, es gibt jedoch auch einen bedingten Operator.
Der Fall, in dem das nächste () der Ergebnismenge mit der Beurteilungsmethode verwechselt wurde, ob es das nächste gibt
Was ist eine Klasse in der Java-Sprache (3 /?)
Gibt es eine numerische Version von include?
Was ist eine Klasse in der Java-Sprache (1 /?)
Lassen Sie uns eine Java-Entwicklungsumgebung erstellen (Aktualisierung)
Was ist eine Klasse in der Java-Sprache (2 /?)
Erstellen Sie eine temporäre Klasse mit new Object () {}
So überprüfen Sie, ob eine Instanzvariable in einer Ruby-Klasse definiert ist
[Android] Erstellen Sie eine neue Klasse, indem Sie ImageView erben
Erstellen wir eine REST-API mit WildFly Swarm.
Lassen Sie uns mit Javas Timer einen zeitgesteuerten Prozess erstellen! !!
Erstellen Sie mit SwiftUI 2.0 eine benutzerdefinierte Registerkartenansicht
So erstellen Sie eine Klasse, die Klasseninformationen erbt
Lassen Sie uns mit Java ein supereinfaches Webframework erstellen
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [Einführung]
[Java] Erstellen wir einen Minecraft Mod 1.16.1 [Einführung]
[Java] Erstellen wir einen Minecraft Mod 1.14.4 [99. Mod-Ausgabe]