我想创建一个带有ActiveRecord验证的Rails(2.1和2.2)模型,但是没有数据库表。什么是最广泛使用的方法?我找到了一些声称可以提供此功能的插件,但是其中许多插件似乎并未得到广泛使用或维护。社区推荐我做什么?现在,我倾向于根据此博客文章提出自己的解决方案。
我想创建一个带有ActiveRecord验证的Rails(2.1和2.2)模型,但是没有数据库表。什么是最广泛使用的方法?我找到了一些声称可以提供此功能的插件,但是其中许多插件似乎并未得到广泛使用或维护。社区推荐我做什么?现在,我倾向于根据此博客文章提出自己的解决方案。
Answers:
我认为您链接的博客文章是最好的选择。我只建议将残存的方法移到模块中,以免污染您的代码。
在Rails 3中,有一种更好的方法可以做到这一点:http : //railscasts.com/episodes/219-active-model
这是我过去使用的一种方法:
在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
在app / models / 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>>
现在有一种更简单的方法:
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
只需在您的“ models /”目录中遵循您惯用的约定(文件名和类名为单数,下划线为文件名,驼峰为类名)创建一个以“ .rb”结尾的新文件。这里的关键是不要从ActiveRecord继承您的模型(因为是AR提供了数据库功能)。例如:对于新的汽车模型,请在您的models /目录和模型内部创建一个名为“ 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类,也许您会找到更好的解决方案;)
由Ryan Bates组成的有关非Active Record模型的截屏视频。一个很好的起点。
以防万一您还没有看过它。
根据John Topley的建议,我构建了一个快速的Mixin来处理此问题。
使用Validatable gem。如您所说,有基于AR的解决方案,但它们往往很脆弱。
有人曾经试图包括ActiveRecord::Validations
和ActiveRecord::Validations::ClassMethods
在非Active Record类,看看想设置验证时,会发生什么?
我确信验证框架和ActiveRecord本身之间存在很多依赖关系。但是您可以通过从AR验证框架中派生自己的验证框架来成功摆脱那些依赖关系。
只是一个想法。
更新:糟糕,这或多或少是与您的问题相关的博文中所建议的内容。对不起,打扰了。
就像Tiago Pinto所说的那样,只是不要让您的模型继承自ActiveRecord :: Base。它只是一个常规的Ruby类,您可以将其粘贴在app / models /目录中的文件中。如果您的模型都没有表,并且您的应用程序中根本没有使用数据库或ActiveRecord,请确保将您的environment.rb文件修改为以下行:
config.frameworks -= [:active_record]
这应该在Rails::Initializer.run do |config|
块内。
您应该签出PassiveRecord插件。它为非数据库模型提供了类似于ActiveRecord的界面。这很简单,并且比与ActiveRecord战斗更省力。
我们将PassiveRecord与Validatable gem结合使用,以获取OP所需的行为。