ActiveRecord::Base Without Table

2019-01-08 10:29发布

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.

8条回答
我只想做你的唯一
2楼-- · 2019-01-08 10:38

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.

查看更多
放我归山
3楼-- · 2019-01-08 10:41

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>>
查看更多
Root(大扎)
4楼-- · 2019-01-08 10:41

I found this link which works BEAUTIFULLY.

http://codetunes.com/2008/07/20/tableless-models-in-rails/

查看更多
疯言疯语
5楼-- · 2019-01-08 10:44

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.

查看更多
beautiful°
6楼-- · 2019-01-08 10:48

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

class MyModel
  include ActiveRecord::Validations

  # ...
end
查看更多
狗以群分
7楼-- · 2019-01-08 10:54

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

查看更多
登录 后发表回答