rails - ActiveRecord:: Base sin tabla
ruby rails active record (8)
Esto surgió hace un momento ( atributos del modelo de rieles sin la columna correspondiente en db ) pero parece que el complemento de Rails mencionado no se mantiene ( http://agilewebdevelopment.com/plugins/activerecord_base_without_table ). ¿No hay forma de hacer esto con ActiveRecord como está?
Si no, ¿hay alguna manera de obtener las reglas de validación de ActiveRecord sin usar ActiveRecord?
ActiveRecord quiere que la tabla exista, por supuesto.
Encontré este enlace que funciona BELLAMENTE.
Este es un enfoque que he usado en el pasado:
En la aplicación / 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
En la aplicación / modelos / foo.rb
class Foo < Tableless
column :bar, :string
validates_presence_of :bar
end
En script / consola
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>>
Este es un formulario de búsqueda que presenta un objeto llamado criterio que tiene un objeto de período anidado con atributos de inicio y fin .
La acción en el controlador es realmente simple, pero carga valores de objetos anidados en el formulario y vuelve a renderizar los mismos valores con mensajes de error si es necesario.
Works on Rails 3.1.
El 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
En el controlador:
def search
@criteria = Criteria.new params[:criteria]
end
En el ayudante:
def criteria_index_path ct, options = {}
url_for :action => :search
end
En la 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 %>
Produce el 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 : El atributo de acción proporcionado por el helper y el formato de nomenclatura de atributos anidados hace que sea tan simple para el controlador cargar todos los valores a la vez
Hay la gema activerecord-tableless . Es una joya para crear modelos ActiveRecord sin tablas, por lo que tiene soporte para validaciones, asociaciones, tipos. Es compatible con Active Record 2.3, 3.0, 3.2
La forma recomendada de hacerlo en Rails 3.x (utilizando ActiveModel) no admite asociaciones ni tipos.
Las validaciones son simplemente un módulo dentro de ActiveRecord. ¿Has intentado mezclarlos en tu modelo que no es ActiveRecord?
class MyModel
include ActiveRecord::Validations
# ...
end
Me imagino que cuantas más respuestas, mejor, ya que este es uno de los primeros resultados en google al buscar "modelos Rails 3.1 sin tablas"
Implementé lo mismo sin usar ActiveRecord :: Base mientras incluía ActiveRecord :: Validations
El objetivo principal era hacer que todo funcionara de manera formidable, y a continuación he incluido un pago de muestra que no se guardará en ningún lado pero que aún tiene la capacidad de ser validado utilizando las validaciones que todos conocemos y 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 esto ayude a alguien ya que he pasado unas horas tratando de resolver esto hoy.
Solo una adición a la respuesta aceptada:
Haga que sus subclases hereden las columnas principales con:
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
ACTUALIZACIÓN: para Rails 3 esto se puede hacer muy fácil. En Rails 3+ puede usar el nuevo módulo ActiveModel
y sus submódulos. Esto debería funcionar ahora:
class Tableless
include ActiveModel::Validations
attr_accessor :name
validates_presence_of :name
end
Para obtener más información, puede consultar el Railscast (o leer sobre él en AsciiCasts ) sobre el tema, así como esta publicación de blog de Yehuda Katz .
ANTIGUA RESPUESTA SIGUE:
Es posible que deba agregar esto a la solución, propuesta por John Topley en el comentario anterior:
class Tableless
class << self
def table_name
self.name.tableize
end
end
end
class Foo < Tableless; end
Foo.table_name # will return "foos"
Esto le proporciona un nombre de tabla "falso", si lo necesita. Sin este método, Foo::table_name
table_name evaluará a "tablelesses".