ActiveRecord::Base 不带表

发布于 2024-07-23 01:58:28 字数 428 浏览 9 评论 0原文

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

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

当然,ActiveRecord 希望该表存在。

This came up a bit ago ( rails model attributes without corresponding column in db ) but it looks like the Rails plugin mentioned is not maintained ( http://agilewebdevelopment.com/plugins/activerecord_base_without_table ). Is there no way to do this with ActiveRecord as is?

If not, is there any way to get ActiveRecord validation rules without using ActiveRecord?

ActiveRecord wants the table to exist, of course.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不语却知心 2024-07-30 01:58:28

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

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

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

This is an approach I have used in the past:

In 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

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>>
云胡 2024-07-30 01:58:28

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

使您的子类继承父列:

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

Just an addition to the accepted answer:

Make your subclasses inherit the parent columns with:

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
晨敛清荷 2024-07-30 01:58:28

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

class Tableless
  include ActiveModel::Validations

  attr_accessor :name

  validates_presence_of :name
end

有关更多信息,您可以查看 Railscast (或 < a href="http://asciicasts.com/episodes/219-active-model" rel="nofollow noreferrer">在 AsciiCasts 上阅读有关该主题的内容),以及此 Yehuda Katz 的博客文章

旧答案如下:

您可能需要将其添加到约翰·托普利在上一篇评论中提出的解决方案中:

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

UPDATE: For Rails 3 this can be done very easy. In Rails 3+ you can use the new ActiveModel module and its submodules. This should work now:

class Tableless
  include ActiveModel::Validations

  attr_accessor :name

  validates_presence_of :name
end

For more info, you can check out the Railscast (or read about it on AsciiCasts) on the topic, as well as this blog post by Yehuda Katz.

OLD ANSWER FOLLOWS:

You may need to add this to the solution, proposed by John Topley in the previous comment:

class Tableless

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

end

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

This provides you with a "fake" table name, if you need one. Without this method, Foo::table_name will evaluate to "tablelesses".

谜兔 2024-07-30 01:58:28

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

class MyModel
  include ActiveRecord::Validations

  # ...
end

Validations are simply a module within ActiveRecord. Have you tried mixing them into your non-ActiveRecord model?

class MyModel
  include ActiveRecord::Validations

  # ...
end
陈独秀 2024-07-30 01:58:28

我认为答案越多越好,因为这是谷歌搜索“不带表的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

我希望这对某人有帮助,因为我今天花了几个小时试图解决这个问题。

I figure the more answers the better since this is one of the first results in google when searching for "rails 3.1 models without tables"

I've implements the same thing without using ActiveRecord::Base while including the ActiveRecord::Validations

The main goal was to get everything working in formtastic, and below I've included a sample payment that will not get saved anywhere but still has the ability to be validated using the validations we all know and love.

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

I hope this helps someone as I've spent a few hours trying to figure this out today.

浪漫之都 2024-07-30 01:58:28

这是一个搜索表单,它呈现一个名为 criteria 的对象,该对象具有一个带有 beginningend 属性的嵌套 period 对象。

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

适用于 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">

注意:帮助器提供的操作属性以及嵌套属性命名格式使控制器可以非常简单地一次加载所有值

This is a search form that presents an object called criteria that has a nested period object with beginning and end attributes.

The action in the controller is really simple yet it loads values from nested objects on the form and re-renders the same values with error messages if necessary.

Works on Rails 3.1.

The model:

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

In the controller:

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

In the helper:

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

In the view:

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

Produces the 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">

Note: The action attribute provided by the helper and the nested attributes naming format that makes it so simple for the controller to load all the values at once

娇纵 2024-07-30 01:58:28

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

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

There is the activerecord-tableless gem. It's a gem to create tableless ActiveRecord models, so it has support for validations, associations, types. It supports Active Record 2.3, 3.0, 3.2

The recommended way to do it in Rails 3.x (using ActiveModel) has no support for associations nor types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文