Бестабличная модель с ассоциациями ActiveRecord в Rails 3.2
Моя конфигурация приложения включает в себя некоторые значения, которые необходимо использовать в отношениях AR. Я знаю, что это странная и потенциально преступная попытка, но мне нужно сохранить конфигурацию в виде текстового файла, и я, честно говоря, считаю, что у меня есть хороший пример для модели без таблиц. К сожалению, мне сложно убедить AR (Rails 3.2) не искать таблицу. Моя бесстольная модель:
class Tableless < ActiveRecord::Base
def self.table_name
self.name.tableize
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
def self.columns_hash
@columns_hash ||= Hash[columns.map { |column| [column.name, column] }]
end
def self.column_names
@column_names ||= columns.map { |column| column.name }
end
def self.column_defaults
@column_defaults ||= columns.map { |column| [column.name, nil] }.inject({}) { |m, e| m[e[0]] = e[1]; m }
end
def self.descends_from_active_record?
return true
end
def persisted?
return false
end
def save( opts = {} )
options = { :validate => true }.merge(opts)
options[:validate] ? valid? : true
end
end
Это расширяется фактической моделью:
class Stuff < Tableless
has_many :stuff_things
has_many :things, :through => :stuff_things
column :id, :integer
column :name, :string
column :value, :string
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
end
Все это основано на коде, найденном здесь на SO и в других местах, но, увы, я получаю SQLException: нет такой таблицы: stuffs: Есть какие-нибудь подсказки?
2 ответа
Для Rails >= 3.2 есть гем activerecord-tableless. Это жемчужина для создания без таблиц моделей ActiveRecord, поэтому он имеет поддержку для проверок, ассоциаций, типов.
Когда вы используете рекомендованный способ (используя ActiveModel вместо ActiveRecord) для этого в Rails 3.x, не поддерживается ни ассоциация, ни типы.
Для Rails >= 4 вы также можете получить поддержку для валидаций, ассоциаций и некоторых обратных вызовов (например, after_initialize), определив ваши безбланковые классы следующим образом:
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
attr_accessor :id, :name, :value
has_many :stuff_things
has_many :things, :through => :stuff_things
end