Skip to content

Instantly share code, notes, and snippets.

@matpowel
Created July 23, 2011 10:04
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save matpowel/1101257 to your computer and use it in GitHub Desktop.
Save matpowel/1101257 to your computer and use it in GitHub Desktop.
An ActiveRecord emulating Tableless model which works with Rails 3.1
class Tableless < ActiveRecord::Base
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
def self.columns()
@columns ||= [];
end
def self.columns_hash
h = {}
for c in self.columns
h[c.name] = c
end
return h
end
def self.column_defaults
Hash[self.columns.map{ |col|
[col.name, col.default]
}]
end
def self.descends_from_active_record?
return true
end
def persisted?
return false
end
# override the save method to prevent exceptions
def save( validate = true )
validate ? valid? : true
end
end
@clickworkorange
Copy link

I should add that with the example above I get "No such table: 'stuffs'" and not "tablelesses".

@matpowel
Copy link
Author

This all works for me.. note I removed your initialize method as it's superfluous, that's what the default one will do but without the unsafe eval.

class Thing < Tableless
  belongs_to :stuff_thing

  column :stuff_thing_id, :integer
  column :name, :string
end

class StuffThing < Tableless
  belongs_to :stuff
  has_many :things

  column :stuff_id, :integer
end

class Stuff < Tableless
  has_many :stuff_things
  has_many :things, :through => :stuff_things

  column :id, :integer
  column :name, :string
  column :value, :string
end

And then you can use them as normal, except that ARel won't chain the has many through very well, I don't know whether your stuff_things etc are actually real AR models, if they are it will work normally.

1.8.7 :064 >   s = Stuff.new( :id => 10, :name => "foo", :value => "bar" )
WARNING: Can't mass-assign protected attributes: id
 => #<Stuff id: nil, name: "foo", value: "bar"> 
1.8.7 :065 > s.stuff_things << StuffThing.new( :stuff => s )
 => [#<StuffThing stuff_id: nil>] 
1.8.7 :067 > s.stuff_things.length
 => 1
s.things << Thing.new( :name => "wild thing" )
 => [#<Thing stuff_thing_id: nil, name: "wild thing">]

@stevemartin
Copy link

Thanks for this gist, I made this demo with it: https://github.com/stevemartin/tableless_form

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment