Je veux créer un modèle Rails (2.1 et 2.2) avec des validations ActiveRecord, mais sans table de base de données. Quelle est l'approche la plus utilisée? J'ai trouvé des plugins qui prétendent offrir cela mais bon nombre d'entre elles ne semblent pas être largement utilisées ou maintenues. Qu'est-ce que la communauté recommande que je fasse? En ce moment, je penche pour trouver ma propre solution basée sur cet article de blog .
Je pense que le blog que vous liez est la meilleure façon de procéder. Je suggérerais seulement de déplacer les méthodes tronquées dans un module pour ne pas polluer votre code.
Il existe une meilleure façon de le faire dans Rails 3: http://railscasts.com/episodes/219-active-model
C'est une approche que j'ai utilisée dans le passé:
Dans 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
Dans app/models/foo.rb
class Foo < Tableless
column :bar, :string
validates_presence_of :bar
end
Dans script/console
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>>
Il existe maintenant un moyen plus simple:
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
créez simplement un nouveau fichier se terminant par ".rb" selon les conventions auxquelles vous êtes habitué (singulier pour le nom de fichier et le nom de classe, souligné pour le nom de fichier, cas de chameau pour le nom de classe) sur votre répertoire "models /". La clé ici est de ne pas hériter votre modèle d'ActiveRecord (car c'est AR qui vous donne la fonctionnalité de base de données). par exemple: pour un nouveau modèle de voiture, créez un fichier appelé "car.rb" dans votre répertoire models/et à l'intérieur de votre modèle:
class Car
# here goes all your model's stuff
end
edit: btw, si vous voulez des attributs sur votre classe, vous pouvez utiliser ici tout ce que vous utilisez sur Ruby, ajoutez simplement quelques lignes en utilisant "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
edit # 2: après avoir lu le commentaire de Mike, je vous dirais de suivre son chemin si vous voulez toutes les fonctionnalités d'ActiveRecord mais pas de table sur la base de données. Si vous voulez juste une classe Ruby class ordinaire, vous trouverez peut-être mieux cette solution;)
Par souci d'exhaustivité:
Rails maintenant (à V5) dispose d'un module pratique que vous pouvez inclure:
include ActiveModel::Model
Cela vous permet d'initialiser avec un hachage et d'utiliser entre autres des validations.
La documentation complète est ici .
Il y a un screencast sur le modèle d'enregistrement non actif, composé par Ryan Bates. Un bon point de départ.
Juste au cas où vous ne l'auriez pas déjà regardé.
J'ai construit un Mixin rapide pour gérer cela, selon la suggestion de John Topley.
Qu'en est-il du marquage de la classe comme abstrait?
class Car < ActiveRecord::Base
self.abstract = true
end
cela indiquera Rails que la classe Car n'a pas de table correspondante.
[modifier]
cela ne vous aidera pas vraiment si vous devez faire quelque chose comme:
my_car = Car.new
Quelqu'un a déjà essayé d'inclure ActiveRecord::Validations
et ActiveRecord::Validations::ClassMethods
dans une classe d'enregistrement non actif et voyez ce qui se passe lorsque vous essayez de configurer des validateurs?
Je suis sûr qu'il existe de nombreuses dépendances entre le cadre de validation et ActiveRecord lui-même. Mais vous pouvez réussir à vous débarrasser de ces dépendances en forçant votre propre cadre de validation à partir du cadre de validation AR.
Juste une idée.
pdate: oopps, c'est plus ou moins ce qui est suggéré dans le post lié à votre question. Désolé pour le dérangement.
Faites comme Tiago Pinto et ne faites pas hériter votre modèle d'ActiveRecord :: Base. Ce sera juste une classe Ruby régulière que vous collerez dans un fichier dans votre répertoire app/models /. Si aucun de vos modèles n'a de tables et que vous n'utilisez pas une base de données ou ActiveRecord sur tous dans votre application, assurez-vous de modifier votre fichier environment.rb pour avoir la ligne suivante:
config.frameworks -= [:active_record]
Cela devrait être dans le Rails::Initializer.run do |config|
bloquer.
Vous devez vérifier le plugin PassiveRecord . Il vous donne une interface de type ActiveRecord pour les modèles non-base de données. C'est simple et moins compliqué que de combattre ActiveRecord.
Nous utilisons PassiveRecord en combinaison avec la gemme Validatable pour obtenir le comportement souhaité de l'OP.