2008-11-24 7 views
59

Ich möchte ein Rails (2.1 und 2.2) -Modell mit ActiveRecord-Validierungen, aber ohne eine Datenbanktabelle erstellen. Was ist der am weitesten verbreitete Ansatz? Ich habe einige Plugins gefunden, die diese Funktionalität anbieten, aber viele von ihnen scheinen nicht weit verbreitet zu sein oder zu warten. Was empfiehlt die Community? Im Moment lehne ich meine eigene Lösung basierend auf this blog post.Schienenmodell ohne Datenbank

+1

Der Blogbeitrag ist jetzt tot. –

+1

http://www.prestonlee.com/2007/12/29/rails-20-validations-without-extening-activerecordbase/ und doch lebendig unter einem neuen Namen. –

+0

http://web.archive.org/web/20100716123520/http://www.prestonlee.com/2007/12/29/rails-20-validations-without-extension-activerecordbase/ weil es scheint wieder unten zu sein – GDR

Antwort

8

Ich glaube, der Blog-Post Sie verknüpfen sind, ist der beste Weg zu gehen. Ich würde nur vorschlagen, die ausgedrückten Methoden in ein Modul zu verschieben, um Ihren Code nicht zu verschmutzen.

+0

Ich bin mit Honza und ich denke, dass Post ist Ihre einzige Option, wenn Sie AR-Validierungen in Ihrem POCO benötigen. Viel Glück. –

+0

Ich ging voran und tat dies. Arbeitete großartig für meine Bedürfnisse. Vielen Dank. – FlipFlop

+11

Der Beitrag fehlt wenn ich besucht habe Könnten Sie ihn hier posten? – sarunw

8

Erstellen Sie einfach eine neue Datei mit der Endung ".rb" nach den Konventionen, die Sie gewohnt sind (Singular für Dateiname und Klassenname, unterstrichen für Dateiname, camel case für Klassennamen) in Ihrem Verzeichnis "models /" . Der Schlüssel hier ist, Ihr Modell nicht von ActiveRecord zu übernehmen (weil es AR ist, das Ihnen die Datenbankfunktionalität gibt). zB: für ein neues Modell für Autos, erstellen Sie eine Datei namens „car.rb“ in Ihren Modellen/Verzeichnis und in Ihrem Modell:

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

edit: btw, wenn Sie Attribute auf Ihrer Klasse möchten, können Sie verwenden hier alles, was Sie auf Rubin verwenden, fügen Sie einfach ein paar Zeilen mit „attr_accessor“:

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 

bearbeiten # 2: nach Mikes Kommentar zu lesen, würde ich Ihnen sagen, seinen Weg zu gehen, wenn Sie alle der Active die wollen Funktionalität, aber keine Tabelle in der Datenbank. Wenn Sie nur eine gewöhnliche Ruby-Klasse haben möchten, finden Sie vielleicht diese Lösung besser;)

+2

, aber dies gibt ihm nicht die AR-Validierungen. –

+0

guter Punkt. Ich wette, es gibt viele Anwendungsfälle für beide Lösungen :) – tpinto

2

Wie wäre es, die Klasse als abstrakt zu markieren?

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

Dies wird Schienen sagen, dass die Car-Klasse keine entsprechende Tabelle hat.

[Bearbeiten]

dies wird Ihnen nicht wirklich helfen, wenn Sie so wollen, etwas zu tun brauchen werden:

my_car = Car.new 
4

Es gibt eine screencast über nicht-Active Record-Modell, bestehend aus Ryan Bates. Ein guter Ausgangspunkt.

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

+0

wieder löst dies nicht das Problem der Plakate mit AR-Validierungen. –

+0

Ich befolgte diese Anweisungen in meiner App und es funktionierte perfekt. – MattSlay

0

Tun Sie wie Tiago Pinto sagte und lassen Sie Ihr Modell nicht von ActiveRecord :: Base erben. Es ist nur eine reguläre Ruby-Klasse, die Sie in einer Datei in Ihrem app/models/-Verzeichnis speichern. Wenn keine Ihrer Modelle Tabellen haben und Sie nicht eine Datenbank oder Activeüberhaupt in Ihrer Anwendung verwenden, müssen Sie Ihre environment.rb Datei zu ändern, die folgende Zeile haben:

config.frameworks -= [:active_record] 

Dieses innerhalb der sein sollte Rails::Initializer.run do |config| Block.

+0

genau wie Tiago Pintos Antwort wird dies unserem Freund nicht helfen, die AR-Validierungen in seiner Klasse zu benutzen. –

43

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

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>> 
+3

Funktioniert gut und sehr leicht. Rails 2.3 wird ein wenig über das Fehlen einer Tabelle in Skript/Konsole beschweren, aber das Hinzufügen von "self.abstract_class = true" löst das (ohne Instantiierung zu verhindern). –

+0

Das scheint mir scheußlich. Warum sollten Sie von ActiveRecord :: Base erben, wenn Sie kein Datenbank-Backend möchten? Es gibt andere Bibliotheken, die Validierungsfunktionen bereitstellen, die kein Datenbank-Backend voraussetzen. –

+2

@David James: Welche? – Rekin

1

jemand versucht hat jemals ActiveRecord::Validations und ActiveRecord::Validations::ClassMethods in einer nicht-Active Record-Klasse gehören und sehen, was passiert, wenn die Einrichtung Validatoren versuchen?

Ich bin mir sicher, dass es zwischen dem Validierungsframework und ActiveRecord selbst viele Abhängigkeiten gibt. Es kann jedoch gelingen, diese Abhängigkeiten loszuwerden, indem Sie Ihr eigenes Validierungsframework aus dem AR-Validierungsframework abzweigen.

Nur eine Idee.

Aktualisieren: oopps, das ist mehr oder weniger, was in dem Beitrag, der mit Ihrer Frage verbunden ist, vorgeschlagen wird. Entschuldigen Sie die Störung.

+1

Ihre Antwort ist jetzt nützlich, da der Blog-Post nicht mehr existiert. – epochwolf

0

Sie sollten die PassiveRecord Plugin zur Kasse. Es bietet eine ActiveRecord-ähnliche Schnittstelle für Nicht-Datenbankmodelle. Es ist einfach und unkompliziert, als ActiveRecord zu bekämpfen.

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

+0

Die Verbindung ist jetzt tot. – lorefnon

+0

In diesen Tagen würde ich wahrscheinlich ActiveModel und was auch immer ich brauchte. –

66

Es gibt einen besseren Weg, dies in Rails zu tun 3: http://railscasts.com/episodes/219-active-model

+0

Ich habe dich gewählt, weil ich zustimme, dass dies ein sauberer und besserer Weg ist, es zu tun, besonders wenn du ein neues Projekt startest. Ich fand jedoch, dass die Lösung von John Topley besser für ein Projekt ist, in dem viel Code immer noch zu dem Schluss kommt, dass Ihr Modell eine Unterklasse von ActiveRecord :: Base ist. Ein spezifisches Beispiel für diese Methode, die nicht einfach funktioniert, ist, wenn Ihr Code auf einem Drittanbieter-Plugin basiert, das auf ActiveRecord basiert. – Tony

+0

Ja, dieser Ansatz für Rails 3 ist sauber und funktioniert super! –

+4

In Rails 4 gibt es auch ActiveModel :: Model, das viele der ActiveModel-Module und einige andere magische Elemente enthält, damit Sie Ihr (nicht persistierendes oder benutzerdefiniertes) Modell wie ein ActiveRecord-Modell fühlen. – nandinga

15

Es ist einfacher Art und Weise jetzt:

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

+2

Dies ist der Weg jetzt zu gehen –

2

Aus Gründen der Vollständigkeit halber:

Rails jetzt (bei V5) hat ein handliches Modul Sie können sein:

include ActiveModel::Model

Auf diese Weise können Sie mit einem Hash initialisieren und um Validierungen unter andere Dinge.

Vollständige Dokumentation ist here.

Verwandte Themen