没有数据库的 Rails 模型

我想创建一个 Rails (2.1和2.2)模型,它带有 ActiveRecord 验证,但是没有数据库表。使用最广泛的方法是什么?我发现有些插件声称提供了这种功能,但其中许多似乎没有得到广泛使用或维护。社区建议我做什么?现在我倾向于提出我自己的解决方案基于 这篇博文

78067 次浏览

只需创建一个以“。Rb”遵循您在“ model/”目录中习惯的约定(文件名和类名使用单数,文件名使用下划线,类名使用驼峰大小写)。这里的关键是不要从 ActiveRecord 继承您的模型(因为正是 AR 为您提供了数据库功能)。 例如: 对于汽车的新型号,在你的型号/目录和你的型号内创建一个名为“ car.rb”的文件:

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

编辑: 顺便说一下,如果你想要类的属性,你可以在这里使用你在 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

编辑 # 2: 在阅读了 Mike 的评论之后,如果您想要 ActiveRecord 的所有功能,但是数据库中没有表的话,我会告诉您按照他的方式进行。如果您只想要一个普通的 Ruby 类,也许您会发现这个解决方案更好;)

将类标记为抽象类怎么样?

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

这将告诉 Rails Car 类没有对应的表。

[编辑]

如果你需要做的事情是:

my_car = Car.new

我认为你链接的博客文章是最好的方法。我只是建议将存根化的方法移动到一个模块中,以免污染您的代码。

有一个 视频关于非活动记录模型,由瑞安贝茨。一个很好的地方开始。

以防你还没看过。

就像 Tiago Pinto 说的那样,不要让你的模型继承 ActiveRecord: : Base。它只是一个普通的 Ruby 类,你可以把它放在 app/model/目录中的一个文件中。如果你的模型都没有表格,而且你的应用程序中根本没有使用数据库或 ActiveRecord,那么一定要修改你的環.rb 文件,使其包含以下内容:

config.frameworks -= [:active_record]

这应该在 Rails::Initializer.run do |config|块内。

这是我过去使用过的一种方法:

App/model/tableess.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

App/model/foo.rb

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

脚本/控制台

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

任何人都曾经尝试包括 ActiveRecord::ValidationsActiveRecord::Validations::ClassMethods在一个非活动记录类,看看会发生什么时,试图设置验证器?

我确信在验证框架和 ActiveRecord 本身之间有很多依赖关系。但是您可以通过从 AR 验证框架中分支自己的验证框架来成功地摆脱这些依赖性。

只是个想法。

更新 : 哎呀,这或多或少是文章中提到的与你的问题相关的建议。抱歉打扰了。

正如你所说的,有一些基于 AR 的解决方案,但它们往往是脆弱的。

Http://validatable.rubyforge.org/

你应该检查一下 被动记录插件。它为非数据库模型提供了一个类 ActiveRecord 的接口。它很简单,而且比对抗 ActiveRecord 更省事。

我们结合使用 Passive Record 和 有效 gem 来获得 OP 所需的行为。

按照 John Topley 的建议,我已经构建了一个快速的 Mixin 来处理这个问题。

Http://github.com/willrjmarshall/tableless

在 Rails 3: http://railscasts.com/episodes/219-active-model中有一个更好的方法来实现这一点

现在有更简单的办法:

class Model
include ActiveModel::Model


attr_accessor :var


validates :var, presence: true
end

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

为了完整起见:

Rails 现在(V5)有一个方便的模块,您可以包括:

include ActiveModel::Model

这允许您使用散列进行初始化,并在其他事情中使用验证。

完整的文档是 给你