ActiveRecord::不带表的Base

ActiveRecord::不带表的Base,activerecord,ruby-on-rails-2,Activerecord,Ruby On Rails 2,这是在前一段时间提出的(),但似乎没有维护上面提到的Rails插件()。没有办法让ActiveRecord保持原样吗 如果没有,是否有任何方法可以在不使用ActiveRecord的情况下获取ActiveRecord验证规则 当然,ActiveRecord希望表存在。验证只是ActiveRecord中的一个模块。您是否尝试过将它们混合到您的非ActiveRecord模型中 class MyModel include ActiveRecord::Validations # ... end

这是在前一段时间提出的(),但似乎没有维护上面提到的Rails插件()。没有办法让ActiveRecord保持原样吗

如果没有,是否有任何方法可以在不使用ActiveRecord的情况下获取ActiveRecord验证规则


当然,ActiveRecord希望表存在。

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

class MyModel
  include ActiveRecord::Validations

  # ...
end

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

在app/models/tabless.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
class Foo < Tableless
  column :bar, :string  
  validates_presence_of :bar
end
类无表foo=foo.new
=> #
>>有效吗?
=>错误
>>foo.errors
=>#[“不能为空”]},@base=#>

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

class Tableless
  include ActiveModel::Validations

  attr_accessor :name

  validates_presence_of :name
end
有关更多信息,您可以查看主题的(或),以及此

旧答案如下:

您可能需要将此添加到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"
类无表

类这是一个搜索表单,它显示一个名为criteria的对象,该对象具有一个带有开始和结束属性的嵌套句点对象

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

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


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

我认为答案越多越好,因为这是google搜索“rails 3.1模型无表”时的第一个结果之一

在包含ActiveRecord::Validations时,我没有使用ActiveRecord::Base实现相同的功能

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

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
我希望这对某人有所帮助,因为我今天花了几个小时试图弄明白这一点。

确实如此。它是创建无表ActiveRecord模型的一颗宝石,因此它支持验证、关联和类型。它支持活动记录2.3、3.0和3.2


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

只是对公认答案的补充:

使用以下命令使子类继承父列:

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
class-FakeAR专栏还没试过,很有趣。。。我有点想得到免费的initialize方法,但只要验证一下,我就会很高兴…很有趣。我用这个已经有一段时间了,没有问题。谢谢。是的,该解决方案有效,并且确实需要表名补丁,因为在这种情况下,类直接继承自
ActiveRecord::Base
。嗨@Neil Stockbridge,我不确定这完全回答了这个问题。这是一个在没有表的情况下使用Base的工作示例(这是最初的问题)包括使基础工作不带表的代码。这个例子适用于Rails 3.1.0。其他人没有。我认为这可能对其他人有用。上面的示例中不包括验证,但由于表单上的对象是
ActiveRecord::Base
,验证的工作原理与表单上任何其他ActiveRecord对象的工作原理相同。示例可能因包含嵌套对象而变得杂乱无章。。。我想我得试试。查看它,我看不出添加的属性如何被视为一级列。也许他们不需要。。。。不管怎样,现在是+1,谢谢。谢谢,希望在ROR 2中有这样的功能:)但是,您应该包括
ActiveModel::Validations
。要了解更多信息,您可以查看主题上的以及。使子类继承父列:@Xinzz我已经发布了一个gem,activerecord tablefree,它与Rails 5兼容,并实现了此模式(列覆盖停止工作,必须切换到新方法)在Rails 3中,您可以包括ActiveModel::Validations,以及同一名称空间中的许多其他模块,这些模块将为您的模型带来类似ActiveRecord的功能。在rails 4中还有ActiveModel::Model,其中包括许多,让您感觉您的(非持久化或自定义持久化)模型就像ActiveRecord模型一样。2016年的解决方案我发布了一个与rails 5兼容的gem ActiveRecord tablefree,并实现了此模式(activerecord tablefree使用的列覆盖停止工作,必须切换到新方法)我发布了一个与Rails 5兼容的gem activerecord tablefree,并实现了此模式(activerecord tablefree使用的列覆盖停止工作,必须切换到新方法)
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
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