I am trying to create a Active Record tableless Model. My user.rb looks like this
class User < ActiveRecord::Base
class_inheritable_accessor :columns
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
column :name, :text
column :exception, :text
serialize :exception
end
When creating the new object in controller
@user = User.new
I am getting the error
Mysql2::Error: Table 'Sampledb.users' doesn't exist: SHOW FIELDS FROM users
class Tableless
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
def self.attr_accessor(*vars)
@attributes ||= []
@attributes.concat( vars )
super
end
def self.attributes
@attributes
end
def initialize(attributes={})
attributes && attributes.each do |name, value|
send("#{name}=", value) if respond_to? name.to_sym
end
end
def persisted?
false
end
def self.inspect
"#<#{ self.to_s} #{ self.attributes.collect{ |e| ":#{ e }" }.join(', ') }>"
end
end
Few things:
Firstly you are using the Rails2 approach outlined in Railscast 193 when really you should be using the Rails 3 approach, outlined in Railscast 219
You probably don't want to inherit from ActiveRecord::Base when doing this sort of thing.
Read Yehuda Katz's blog post on this.
As mentioned by stephenmurdoch
in rails 3.0+ you can use the method outlined in railscasts 219
I had to make a slight modification to get this to work:
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :content
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :content, :maximum => 500
def initialize(attributes = {})
unless attributes.nil?
attributes.each do |name, value|
send("#{name}=", value)
end
end
end
def persisted?
false
end
end
Don't inherit your class from ActiveRecord::Base
.
If a model inherits from ActiveRecord::Base as you would expect a model class to,it wants to have a database back-end.
Just remove:
class_inheritable_accessor :columns
And it should work, even with associations just like a model with a table.
Just for anyone still struggling with this. For rails 2.x.x
class TestImp < ActiveRecord::Base
def self.columns
@columns ||= []
end
end
For rails 3.1.x you can either include ActiveModel (as explained by @ducktyped) without inheriting from ActiveRecord or If you do need to inherit from ActiveRecord::Base due to some reason then the above with one other addition:
class TestImp < ActiveRecord::Base
def attributes_from_column_definition
[]
end
def self.columns
@columns ||= []
end
end
For Rails >= 3.2 there is the activerecord-tableless gem. Its a gem to create tableless ActiveRecord models, so it has support for validations, associations, types.
When you are using the recommended way to do it in Rails 3.x there is no support for association nor types.
来源:https://stackoverflow.com/questions/9123858/how-to-create-activerecord-tableless-model-in-rails-3