简体   繁体   English

没有数据库的Rails模型

[英]Rails model without database

I want to create a Rails (2.1 and 2.2) model with ActiveRecord validations, but without a database table. 我想创建一个带有ActiveRecord验证的Rails(2.1和2.2)模型,但没有数据库表。 What is the most widely used approach? 什么是最广泛使用的方法? I've found some plugins that claim to offer this functionality, but many of them don't appear to be widely used or maintained. 我发现一些声称提供此功能的插件,但其中许多插件似乎没有得到广泛使用或维护。 What does the community recommend I do? 社区推荐我做什么? Right now I am leaning toward coming up with my own solution based on this blog post . 现在,我倾向于根据这篇博客文章提出我自己的解决方案。

在Rails 3中有更好的方法: http//railscasts.com/episodes/219-active-model

This is an approach I have used in the past: 这是我过去使用的一种方法:

In app/models/tableless.rb 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 app / models / foo.rb中

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

In 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>>

There is easier way now: 现在有更简单的方法:

class Model
  include ActiveModel::Model

  attr_accessor :var

  validates :var, presence: true
end

ActiveModel::Model code: ActiveModel::Model代码:

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 http://api.rubyonrails.org/classes/ActiveModel/Model.html

just create a new file ending in ".rb" following the conventions you're used to (singular for file name and class name, underscored for file name, camel case for class name) on your "models/" directory. 只需创建一个以“.rb”结尾的新文件,遵循您习惯使用的约定(文件名和类名称的单数,文件名的下划线,类名称的驼峰案例)。 The key here is to not inherit your model from ActiveRecord (because it is AR that gives you the database functionality). 这里的关键是不从ActiveRecord继承您的模型(因为它是为您提供数据库功能的AR)。 eg: for a new model for cars, create a file called "car.rb" in your models/ directory and inside your model: 例如:对于汽车的新模型,在模型/目录和模型内创建一个名为“car.rb”的文件:

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

edit: btw, if you want attributes on your class, you can use here everything you use on ruby, just add a couple lines using "attr_accessor": 编辑:顺便说一句,如果你想要你的类的属性,你可以在这里使用你在ruby上使用的所有东西,只需使用“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: after reading Mike's comment, I'd tell you to go his way if you want all of the ActiveRecord's functionality but no table on the database. 编辑#2:在阅读Mike的评论后,如果您想要所有ActiveRecord的功能但数据库上没有表格,我会告诉您。 If you just want an ordinary Ruby class, maybe you'll find this solution better ;) 如果你只是想要一个普通的Ruby类,也许你会发现这个解决方案更好;)

I think the blog post you are linking is the best way to go. 我认为您链接的博客文章是最好的方式。 I would only suggest moving the stubbed out methods into a module not to pollute your code. 我只建议将已删除的方法移动到一个模块中,以免污染您的代码。

For the sake of completeness: 为了完整起见:

Rails now (at V5) has a handy module you can include: Rails现在(在V5)有一个方便的模块,你可以包括:

include ActiveModel::Model

This allows you to initialise with a hash, and use validations amongst other things. 这允许您使用哈希初始化,并使用其他方面的验证。

Full documentation is here . 完整的文档在这里

There's a screencast about non-Active Record model, made up by Ryan Bates. 有一个关于非活动记录模型的截屏视频 ,由Ryan Bates编写。 A good place to start from. 一个好的起点。

Just in case you did not already watch it. 以防您没有看过它。

I have built a quick Mixin to handle this, as per John Topley's suggestion. 根据John Topley的建议,我已经建立了一个快速的Mixin来处理这个问题。

http://github.com/willrjmarshall/Tableless http://github.com/willrjmarshall/Tableless

What about marking the class as abstract? 把这个类标记为抽象怎么样?

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

this will tell rails that the Car class has no corresponding table. 这将告诉rails,Car类没有相应的表。

[edit] [编辑]

this won't really help you if you'll need to do something like: 如果您需要执行以下操作,这对您不会有任何帮助:

my_car = Car.new

Use the Validatable gem. 使用Validatable gem。 As you say, there are AR-based solutions, but they tend to be brittle. 如你所说,有基于AR的解决方案,但它们往往是脆弱的。

http://validatable.rubyforge.org/ http://validatable.rubyforge.org/

Anybody has ever tried to include ActiveRecord::Validations and ActiveRecord::Validations::ClassMethods in a non-Active Record class and see what happens when trying to setup validators ? 有人试过在非Active Record类中包含ActiveRecord::ValidationsActiveRecord::Validations::ClassMethods ,看看尝试设置验证器时会发生什么?

I'm sure there are plenty of dependencies between the validation framework and ActiveRecord itself. 我确信验证框架和ActiveRecord本身之间存在大量依赖关系。 But you may succeed in getting rid of those dependencies by forking your own validation framework from the AR validation framework. 但是,您可以通过从AR验证框架中分配自己的验证框架来成功摆脱这些依赖关系。

Just an idea. 只是一个想法。

Update : oopps, this is more or less what's suggested in the post linked with your question. 更新 :oopps,这或多或少与您的问题链接的帖子中的建议。 Sorry for the disturbance. 对不起,打扰了。

You ought to checkout the PassiveRecord plugin. 你应该检查PassiveRecord插件。 It gives you an ActiveRecord-like interface for non-database models. 它为非数据库模型提供了类似ActiveRecord的接口。 It's simple, and less hassle than fighting ActiveRecord. 它比ActiveRecord更简单,更轻松。

We're using PassiveRecord in combination with the Validatable gem to get the OP's desired behaviour. 我们将PassiveRecord与Validatable gem结合使用以获得OP所需的行为。

Do like Tiago Pinto said and just don't have your model inherit from ActiveRecord::Base. 就像Tiago Pinto说的那样,只是没有你的模型继承自ActiveRecord :: Base。 It'll just be a regular Ruby class that you stick in a file in your app/models/ directory. 它只是一个常规的Ruby类,您可以将其粘贴到app / models /目录中的文件中。 If none of your models have tables and you're not using a database or ActiveRecord at all in your app, be sure to modify your environment.rb file to have the following line: 如果您的应用中没有任何模型具有表,并且您根本没有使用数据库或ActiveRecord,请务必修改environment.rb文件以使其具有以下行:

config.frameworks -= [:active_record]

This should be within the Rails::Initializer.run do |config| 这应该在Rails::Initializer.run do |config| block. 块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM