ruby-on-rails - generate - ruby on rails tutorial
¿Tipos de modelos y clasificación en Rails? (4)
Correcto, entonces @ foo.inspect te da "nil" en el registro?
Lo que quiero decir (si no fuera lo suficientemente claro) fue:
def create
@foo = RedFoo.new(params[:foo])
logger.error "******************* foo: #{@foo.inspect} **************"
respond_to do |format|
if @foo.save
...
Si haces eso y rastreas tu registro, puedes averiguar fácilmente qué está pasando con foo y compararlo con el hash de params entrantes.
De hecho, esa también sería una información útil, ¿qué es hash params?
Esto es algo en lo que he estado estancado desde hace un tiempo, y tengo que disculparme por adelantado por entrar en tantos detalles para un problema tan simple. Solo quiero dejar en claro lo que estoy tratando de hacer aquí.
Guión
Entonces, hay un modelo Foo, cada Foo puede ser rojo, verde o azul. Tener URL como /reds
para enumerar todos los objetos rojos, y /reds/some-red-object
para mostrar un determinado objeto. En esa vista de "mostrar", debería haber enlaces próximos / anteriores, que esencialmente "encontrarían el siguiente RedFoo en orden alfabético, y una vez en el último RedFoo, el siguiente registro debería ser el primer GreenFoo, continuando en orden alfabético, y así en".
Intenté implementar esto de varias maneras y, en general, terminé en una barricada en alguna parte. Lo logré trabajando en su mayor parte con herencia de mesa única, teniendo algo como esto:
class Foo < ActiveRecord::Base
class RedFoo < Foo
class GreenFoo < Foo
class BlueFoo < Foo
Los modelos y controladores de cada subclase son idénticos, simplemente reemplace los nombres de los modelos. Entonces los controladores se ven algo así como:
class RedFoosController < ApplicationController
def index
@foos = RedFoo.find(:all, :order => "title ASC")
respond_to do |format|
format.html { render :template => ''foos/index''}
format.xml { render :xml => @foos }
end
end
def show
@foo = RedFoo.find(params[:id])
respond_to do |format|
format.html { render :template => ''foos/show''}
format.xml { render :xml => @foo }
end
end
def new
@foo = RedFoo.new
respond_to do |format|
format.html { render :template => ''foos/new''}
format.xml { render :xml => @foo }
end
end
def edit
@foo = RedFoo.find(params[:id])
respond_to do |format|
format.html { render :template => ''foos/edit''}
end
end
def create
@foo = RedFoo.new(params[:foo])
respond_to do |format|
if @foo.save
flash[:notice] = ''Foo was successfully created.''
format.html { redirect_to(@foo) }
format.xml { render :xml => @foo, :status => :created, :location => @foo }
else
format.html { render :action => "new" }
format.xml { render :xml => @foo.errors, :status => :unprocessable_entity }
end
end
end
def update
@foo = RedFoo.find(params[:id])
respond_to do |format|
if @foo.update_attributes(params[:foo])
flash[:notice] = ''Foo was successfully updated.''
format.html { redirect_to(@foo) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @foo.errors, :status => :unprocessable_entity }
end
end
end
def destroy
@foo = RedFoo.find(params[:id])
@foo.destroy
respond_to do |format|
format.html { redirect_to(foos_url) }
format.xml { head :ok }
end
end
end
Los modelos solo contienen métodos para siguiente / anterior, que funcionan bien, sorprendentemente.
class RedFoo < Foo
def next
if self == RedFoo.find(:all, :order => "title ASC").last
GreenFoo.find(:all, :order => "title ASC").first
else
RedFoo.find(:first, :conditions => ["title > ?", self.title], :order => "title ASC")
end
end
def previous
if self == RedFoo.find(:all, :order => "title ASC").first
BlueFoo.find(:all, :order => "title ASC").last
else
RedFoo.find(:first, :conditions => ["title < ?", self.title], :order => "title DESC")
end
end
end
Problema
Por alguna razón, cuando intento crear y editar registros, ninguno de los atributos se guarda en la base de datos. Simplemente agrega un nuevo registro con columnas completamente vacías, independientemente de lo que haya rellenado el formulario. No se devuelve ningún error en la secuencia de comandos / salida del servidor o en los archivos de registro. Sin embargo, desde el script / consola, todo funciona perfectamente bien. Puedo crear nuevos registros y actualizar sus atributos sin problema.
También es un mal olor de código que tengo mucha duplicación de código en mis controladores / modelos (están usando las mismas vistas que el modelo base, así que está bien). Pero creo que eso es inevitable aquí a menos que use algo de meta-bondad.
Cualquier consejo o sugerencia para abordar este problema de grabación de registros sería genial, pero la razón por la que publiqué mi configuración en detalle es porque tengo la sensación de que probablemente estoy haciendo todo esto de la manera equivocada. Entonces, estoy abierto a otros enfoques si conoces algo más práctico que usar STI. Gracias.
Actualizar
Los parámetros hash se ven a la derecha:
{"commit"=>"Create", "authenticity_token"=>"+aOA6bBSrZP2B6jsDMnKTU+DIAIkhc8fqoSicVxRJls=", "red_foo"=>{"title"=>"Hello world!"}}
Pero @ foo.inspect devuelve el siguiente objeto RedFoo (todo nulo, excepto el tipo):
#<RedFoo id: nil, title: nil, type: "RedFoo", created_at: nil, updated_at: nil>
Debo admitir que la forma en que voy sobre STI es usar set_table_name dentro de un modelo.
p.ej
class RedFoo < AR::Base
set_table_name "foos"
include FooModule
extend FooClassModule # for self methods
def next; ...; end
end
Pero de todos modos, para esta situación, ¿qué dice tu registrador cuando haces un @ foo.inspect justo antes de guardar, y también qué es el SQL que se ejecuta en insert / update?
Por favor, eche un vistazo a la sección llamada "herencia de tabla única" en esta página y avísenos si resuelve su problema.
El problema es el params
:red_foo
es el nombre de los params en la vista, mientras que usted usa
params[:foo]
en el controlador, creo que la mejor manera sería usar: foo, en la vista usando text_field_tag en lugar de cualquiera (lo que supongo que puede ser) form builders text_field.
Puedes salir del olor del controlador usando un módulo para hacer las cosas básicas, ya que supongo que la mayoría de las cosas nuevas / crear / editar / actualizar / destruir son las mismas
O
puede mapear todas las rutas a un controlador foo y usar algún tipo de parámetro, ya sea pasado desde la ruta, o mediante el análisis URI para obtener el foo rojo / verde / azul