23

这在不久前出现(rails 模型属性在 db 中没有相应的列),但看起来提到的 Rails 插件没有维护(http://agilewebdevelopment.com/plugins/activerecord_base_without_table)。有没有办法用 ActiveRecord 做到这一点?

如果没有,有没有办法在不使用 ActiveRecord 的情况下获取 ActiveRecord 验证规则?

ActiveRecord 当然希望表存在。

4

7 回答 7

39

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

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>>
于 2009-06-02T10:10:08.297 回答
17

验证只是 ActiveRecord 中的一个模块。您是否尝试将它们混合到您的非 ActiveRecord 模型中?

class MyModel
  include ActiveRecord::Validations

  # ...
end
于 2009-06-02T02:56:42.503 回答
9

我认为答案越多越好,因为这是在谷歌搜索“没有表格的 Rails 3.1 模型”时的第一个结果之一

我在不使用 ActiveRecord::Base 的情况下实现了同样的事情,同时包含了 ActiveRecord::Validations

主要目标是让一切都以形式进行,下面我提供了一个示例付款,它不会保存在任何地方,但仍然能够使用我们都知道和喜爱的验证进行验证。

class Payment
  include ActiveModel::Validations
  attr_accessor :cc_number, :payment_type, :exp_mm, :exp_yy, :card_security, :first_name, :last_name, :address_1, :address_2, :city, :state, :zip_code, :home_telephone, :email, :new_record

  validates_presence_of :cc_number, :payment_type, :exp_mm, :exp_yy, :card_security, :first_name, :last_name, :address_1, :address_2, :city, :state

  def initialize(options = {})
    if options.blank?
      new_record = true
    else
      new_record = false
    end
    options.each do |key, value|
      method_object = self.method((key + "=").to_sym)
      method_object.call(value)
    end
  end

  def new_record?
    return new_record
  end

  def to_key
  end

  def persisted?
    return false
  end
end

我希望这对某人有所帮助,因为我今天花了几个小时试图弄清楚这一点。

于 2011-11-29T23:37:30.537 回答
8

更新:对于 Rails 3,这可以很容易地完成。在 Rails 3+ 中,您可以使用新ActiveModel模块及其子模块。现在应该可以了:

class Tableless
  include ActiveModel::Validations

  attr_accessor :name

  validates_presence_of :name
end

有关更多信息,您可以查看有关该主题的Railscast(或在 AsciiCasts 上阅读),以及Yehuda Katz 的这篇博客文章

旧答案如下:

您可能需要将此添加到解决方案中,由 John Topley 在之前的评论中提出:

class Tableless

  class << self
    def table_name
      self.name.tableize
    end
  end

end

class Foo < Tableless; end
Foo.table_name # will return "foos"

如果您需要,这会为您提供一个“假”表名。如果没有这种方法,Foo::table_name将评估为“tablelesses”。

于 2009-12-17T15:55:39.810 回答
2

只是对已接受答案的补充:

使您的子类继承父列:

class FakeAR < ActiveRecord::Base
  def self.inherited(subclass)
    subclass.instance_variable_set("@columns", columns)
    super
  end

  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

  # Overrides save to prevent exceptions.
  def save(validate = true)
    validate ? valid? : true
  end
end
于 2013-08-14T17:02:33.810 回答
1

这是一个搜索表单,它显示了一个称为条件的对象,该条件具有一个嵌套的点对象,其中包含开始结束属性。

控制器中的操作非常简单,但它会从表单上的嵌套对象加载值,并在必要时使用错误消息重新呈现相同的值。

在 Rails 3.1 上工作。

该模型:

class Criteria < ActiveRecord::Base
  class << self

    def column_defaults
      {}
    end

    def column_names
      []
    end
  end # of class methods

  attr_reader :period

  def initialize values
    values ||= {}
    @period = Period.new values[:period] || {}
    super values
  end

  def period_attributes
    @period
  end
  def period_attributes= new_values
    @period.attributes = new_values
  end
end

在控制器中:

def search
  @criteria = Criteria.new params[:criteria]
end

在助手中:

def criteria_index_path ct, options = {}
  url_for :action => :search
end

在视图中:

<%= form_for @criteria do |form| %>
  <%= form.fields_for :period do |prf| %>
    <%= prf.text_field :beginning_as_text %>
    <%= prf.text_field :end_as_text %>
  <% end %>
  <%= form.submit "Search" %>
<% end %>

生成 HTML:

<form action="/admin/search" id="new_criteria" method="post">
  <input id="criteria_period_attributes_beginning_as_text" name="criteria[period_attributes][beginning_as_text]" type="text"> 
  <input id="criteria_period_attributes_end_as_text" name="criteria[period_attributes][end_as_text]" type="text">

注意:助手提供的动作属性和嵌套属性命名格式使得控制器一次加载所有值变得如此简单

于 2011-10-25T20:53:15.650 回答
1

activerecord-tableless gem。它是创建无表 ActiveRecord 模型的宝石,因此它支持验证、关联和类型。它支持 Active Record 2.3、3.0、3.2

在 Rails 3.x 中推荐的方法(使用 ActiveModel)不支持关联或类型。

于 2013-02-20T14:12:16.240 回答