Schienenmodell ohne Datenbank

68

Ich möchte ein Rails-Modell (2.1 und 2.2) mit ActiveRecord-Validierungen erstellen, jedoch ohne Datenbanktabelle. Was ist der am weitesten verbreitete Ansatz? Ich habe einige Plugins gefunden, die behaupten, diese Funktionalität anzubieten, aber viele von ihnen scheinen nicht weit verbreitet zu sein oder gewartet zu werden. Was empfiehlt die Community mir? Im Moment neige ich dazu, meine eigene Lösung basierend auf diesem Blog-Beitrag zu entwickeln .

Flip Flops
quelle
1
Der verlinkte Blog-Beitrag ist jetzt tot.
Jeremy B.
1
prestonlee.com/2007/12/29/… und doch lebendig unter einem neuen Namen.
Tim Snowhite
web.archive.org/web/20100716123520/http://www.prestonlee.com/… weil es wieder unten zu sein scheint
DDR
1
Dies scheint ein Duplikat von stackoverflow.com/questions/937429/… zu sein, das tatsächlich eine bessere Lösung vorschlägt.
Michal

Antworten:

9

Ich denke, der Blog-Beitrag, den Sie verlinken, ist der beste Weg. Ich würde nur empfehlen, die ausgeblendeten Methoden in ein Modul zu verschieben, um Ihren Code nicht zu verschmutzen.

Honza
quelle
Ich bin bei Honza und ich denke, dass der Beitrag Ihre einzige Option ist, wenn Sie die Validierungen von AR in Ihren POCOs benötigen. Viel Glück.
Mike Breen
11
Der Beitrag fehlt bei meinem Besuch. Könnten Sie ihn hier posten?
Sarunw
Rails führte ActiveModel ein, um dieses Problem zu lösen - es gibt eine Antwort, die dies unter stackoverflow.com/a/34354961/1511504 abdeckt
notapatch
69

In Rails 3 gibt es eine bessere Möglichkeit, dies zu tun: http://railscasts.com/episodes/219-active-model

d135-1r43
quelle
Ich habe Sie gewählt, weil ich damit einverstanden bin, dass dies ein sauberer und besserer Weg ist, insbesondere wenn Sie ein neues Projekt starten. Ich fand jedoch, dass John Topleys Lösung in einem Projekt besser ist, in dem noch viel Code denken muss, dass Ihr Modell eine Unterklasse von ActiveRecord :: Base ist. Ein spezielles Beispiel für diese Methode, die nicht einfach funktioniert, ist, wenn Ihr Code auf einem Plugin eines Drittanbieters basiert, das auf ActiveRecord basiert.
Tony
6
In Rails 4 gibt es auch ActiveModel :: Model, das viele der ActiveModel-Module und einige andere magische Elemente enthält, damit Sie Ihr (nicht persistiertes oder benutzerdefiniertes) Modell wie ein ActiveRecord-Modell fühlen.
Nandilugio
43

Dies ist ein Ansatz, den ich in der Vergangenheit verwendet habe:

In app / models / tableless.rb

class Tableless < ActiveRecord::Base
  def self.columns
    @columns ||= [];
  end

  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default,
      sql_type.to_s, null)
  end

  # Override the save method to prevent exceptions.
  def save(validate = true)
    validate ? valid? : true
  end
end

In app / models / foo.rb.

class Foo < Tableless
  column :bar, :string  
  validates_presence_of :bar
end

In Skript / Konsole

Loading development environment (Rails 2.2.2)
>> foo = Foo.new
=> #<Foo bar: nil>
>> foo.valid?
=> false
>> foo.errors
=> #<ActiveRecord::Errors:0x235b270 @errors={"bar"=>["can't be blank"]}, @base=#<Foo bar: nil>>
John Topley
quelle
3
Funktioniert gut und sehr leicht. Rails 2.3 wird sich ein wenig über das Fehlen einer Tabelle in Skript / Konsole beschweren, aber das Hinzufügen von "self.abstract_class = true" löst dies (ohne die Instanziierung zu verhindern).
Andrew Hodgkinson
Das scheint mir schrecklich. Warum von ActiveRecord :: Base erben, wenn Sie kein Datenbank-Backend möchten? Es gibt andere Bibliotheken, die Validierungsfunktionen bereitstellen, die kein Datenbank-Backend voraussetzen.
David J.
@David. Ok, das ist einer. Irgendwelche anderen?
Rekin
Nur zur Aufzeichnung: Die erste Option ( stackoverflow.com/questions/3416484/… ) gilt nur für Rails 3.
Gorn
23

Es gibt jetzt einen einfacheren Weg:

class Model
  include ActiveModel::Model

  attr_accessor :var

  validates :var, presence: true
end

ActiveModel::Model Code:

module ActiveModel
  module Model
    def self.included(base)
      base.class_eval do
        extend  ActiveModel::Naming
        extend  ActiveModel::Translation
        include ActiveModel::Validations
        include ActiveModel::Conversion
      end
    end

    def initialize(params={})
      params.each do |attr, value|
        self.public_send("#{attr}=", value)
      end if params
    end

    def persisted?
      false
    end
  end
end

http://api.rubyonrails.org/classes/ActiveModel/Model.html

hlcs
quelle
2
Dies ist der richtige Weg jetzt
Alex Rodriguez Lopez
7

Erstellen Sie einfach eine neue Datei mit der Endung ".rb" gemäß den gewohnten Konventionen (Singular für Dateiname und Klassenname, unterstrichen für Dateiname, Kamelfall für Klassenname) in Ihrem Verzeichnis "models /". Der Schlüssel hier ist, Ihr Modell nicht von ActiveRecord zu erben (da AR Ihnen die Datenbankfunktionalität bietet). Beispiel: Erstellen Sie für ein neues Modell für Autos eine Datei mit dem Namen "car.rb" in Ihrem Modellverzeichnis und in Ihrem Modell:

class Car
    # here goes all your model's stuff
end

edit: Übrigens, wenn du Attribute für deine Klasse haben willst, kannst du hier alles verwenden, was du für Ruby verwendest. Füge einfach ein paar Zeilen mit "attr_accessor" hinzu:

class Car
    attr_accessor :wheels # this will create for you the reader and writer for this attribute
    attr_accessor :doors # ya, this will do the same

    # here goes all your model's stuff
end

edit # 2: Nachdem Sie Mikes Kommentar gelesen haben, würde ich Ihnen sagen, dass Sie seinen Weg gehen sollen, wenn Sie alle Funktionen von ActiveRecord, aber keine Tabelle in der Datenbank haben möchten. Wenn Sie nur eine gewöhnliche Ruby-Klasse wollen, finden Sie diese Lösung vielleicht besser;)

tpinto
quelle
2
Dies gibt ihm jedoch nicht die AR-Validierungen.
Mike Breen
guter Punkt. Ich wette, es gibt viele Anwendungsfälle für beide Lösungen :)
Bis
5

Der Vollständigkeit halber:

Rails now (bei V5) hat ein praktisches Modul, das Sie einschließen können:

include ActiveModel::Model

Auf diese Weise können Sie mit einem Hash initialisieren und unter anderem Validierungen verwenden.

Die vollständige Dokumentation finden Sie hier .

xmjw
quelle
4

Es gibt einen Screencast über ein nicht aktives Rekordmodell, der von Ryan Bates erstellt wurde. Ein guter Ausgangspunkt.

Nur für den Fall, dass Sie es noch nicht gesehen haben.

Laurent Farcy
quelle
Auch dies löst nicht das Posterproblem der Verwendung von AR-Validierungen.
Mike Breen
Ich habe diese Anweisungen in meiner App befolgt und es hat perfekt funktioniert.
MattSlay
2

Was ist mit dem Markieren der Klasse als abstrakt?

class Car < ActiveRecord::Base
  self.abstract = true
end

Dadurch wird den Schienen mitgeteilt, dass die Fahrzeugklasse keine entsprechende Tabelle hat.

[bearbeiten]

Dies hilft Ihnen nicht wirklich, wenn Sie Folgendes tun müssen:

my_car = Car.new
Mike Breen
quelle
2

Verwenden Sie den validierbaren Edelstein. Wie Sie sagen, gibt es AR-basierte Lösungen, die jedoch tendenziell spröde sind.

http://validatable.rubyforge.org/


quelle
1

Jeder hat schon einmal versucht , zu schließen ActiveRecord::Validationsund ActiveRecord::Validations::ClassMethodsin einer nicht-Active Record - Klasse und sieht , was passiert , wenn die Einrichtung Validatoren versuchen?

Ich bin sicher, dass es viele Abhängigkeiten zwischen dem Validierungsframework und ActiveRecord selbst gibt. Möglicherweise gelingt es Ihnen jedoch, diese Abhängigkeiten zu beseitigen, indem Sie Ihr eigenes Validierungsframework aus dem AR-Validierungsframework ableiten.

Nur eine Idee.

Update : oopps, das ist mehr oder weniger das, was in dem mit Ihrer Frage verknüpften Beitrag vorgeschlagen wird. Entschuldigen Sie die Störung.

Laurent Farcy
quelle
1
Ihre Antwort ist jetzt nützlich, da der Blog-Beitrag nicht mehr existiert.
Epochwolf
0

Machen Sie es wie Tiago Pinto und lassen Sie Ihr Modell nicht von ActiveRecord :: Base erben. Es ist nur eine reguläre Ruby-Klasse, die Sie in eine Datei in Ihrem Verzeichnis app / models / stecken. Wenn keines Ihrer Modelle Tabellen enthält und Sie in Ihrer App überhaupt keine Datenbank oder ActiveRecord verwenden, müssen Sie Ihre Datei environment.rb so ändern, dass die folgende Zeile angezeigt wird:

config.frameworks -= [:active_record]

Dies sollte innerhalb des Rails::Initializer.run do |config|Blocks sein.

Sarah Vessels
quelle
Genau wie die Antwort von Tiago Pinto hilft dies unserem Freund nicht, die AR-Validierungen in seiner Klasse zu verwenden.
Mike Breen
0

Sie sollten das PassiveRecord- Plugin auschecken . Es bietet Ihnen eine ActiveRecord-ähnliche Schnittstelle für Nicht-Datenbankmodelle. Es ist einfach und weniger problematisch als der Kampf gegen ActiveRecord.

Wir verwenden PassiveRecord in Kombination mit dem Juwel Validatable , um das gewünschte Verhalten des OP zu erhalten.

Tate Johnson
quelle
In diesen Tagen würde ich wahrscheinlich ActiveModel und alles, was ich sonst noch brauchte, einschließen.
Tate Johnson