ActiveRecord :: base sem Tabela
-
06-09-2019 - |
Pergunta
Este veio um pouco atrás ( trilhos atributos modelo, sem coluna correspondente no db ), mas parece que as Rails plugin é mencionados não conservado ( http://agilewebdevelopment.com/plugins/activerecord_base_without_table ). Não há nenhuma maneira de fazer isso com ActiveRecord como é?
Se não, há alguma maneira de obter regras de validação ActiveRecord sem usar ActiveRecord?
ActiveRecord quer a tabela de existir, é claro.
Solução
Esta é uma abordagem que tenho usado no passado:
Em 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
Em app / models / foo.rb
class Foo < Tableless
column :bar, :string
validates_presence_of :bar
end
Em 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>>
Outras dicas
As validações são simplesmente um módulo dentro ActiveRecord. Você tentou misturar-los em seu modelo não-ActiveRecord?
class MyModel
include ActiveRecord::Validations
# ...
end
Eu acho que as respostas mais melhor uma vez que este é um dos primeiros resultados no Google ao procurar por "trilhos 3.1 modelos sem tabelas"
Eu tenho implementa a mesma coisa sem usar ActiveRecord :: Base, enquanto incluindo os ActiveRecord :: validações
O principal objetivo era conseguir tudo que trabalham em Formtastic, e abaixo eu incluí um pagamento amostra que não vai ser salvo em qualquer lugar, mas ainda tem a capacidade de ser validado usando as validações que todos nós conhecemos e amamos.
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
Espero que isso ajude alguém como eu passei algumas horas tentando descobrir isso hoje.
UPDATE: Para Rails 3 isto pode ser feito muito fácil. No Rails 3 + você pode usar o novo módulo ActiveModel
e seus submódulos. Isso deve funcionar agora:
class Tableless
include ActiveModel::Validations
attr_accessor :name
validates_presence_of :name
end
Para obter mais informações, você pode conferir o Railscast (ou ler sobre ele em AsciiCasts ) sobre o tema, assim como este blog por Yehuda Katz .
RESPOSTA VELHO SEGUINTE:
Você pode precisar adicionar esta à solução, proposta por John Topley no comentário anterior:
class Tableless
class << self
def table_name
self.name.tableize
end
end
end
class Foo < Tableless; end
Foo.table_name # will return "foos"
Isto proporciona-lhe um "fake" nome da tabela, se você precisa de um. Sem este método, Foo::table_name
irá avaliar a "tablelesses".
Eu encontrei este link que funciona lindamente.
http://codetunes.com/2008/07/ 20 /-tableless-modelos-in rails /
Apenas um complemento para a resposta aceita:
Faça suas subclasses herdam as colunas pai com:
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
Este é um formulário de pesquisa que apresenta um objeto chamado critérios que tem um período objeto aninhado com início e final atributos.
A ação no controlador é realmente simples, mas ele carrega valores de objetos aninhados no formulário e re-processa os mesmos valores com mensagens de erro, se necessário.
Os trabalhos no Rails 3.1.
O modelo:
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
No controlador:
def search
@criteria = Criteria.new params[:criteria]
end
No helper:
def criteria_index_path ct, options = {}
url_for :action => :search
end
Do ponto de vista:
<%= 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 %>
Produz o 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">
Nota ??strong>: O atributo action fornecido pelo ajudante e os atributos aninhados formato que faz de nomeação tão simples para o controlador para carregar todos os valores de uma só vez
Há o activerecord-tableless gem . É uma jóia para criar modelos tableless ActiveRecord, então ele tem suporte para validações, associações, tipos. Ele suporta Active Record 2.3, 3.0, 3.2
A maneira recomendada para fazê-lo em Rails 3.x (usando ActiveModel) não tem suporte para associações nem tipos.