Ayuda con vista "complicada"

Veréis estoy modelando las acciones que se pueden hacer con una
plantilla de un equipo de fútbol, y ahora estoy intentando implementar
la acción de cambiar a un jugador de mi plantilla de posición. Ahora
mismo estoy haciendo la implementación sin pensar en usar código
JavaScript para que así mi aplicación sea totalmente compatible con
navegadores con JS desactivado. Bien, actualmente mi vista se renderiza
de esta forma:

Plantilla del Club:

Titulares:

Nombre Apellidos Posicion Calidad
Carlos Belizón 1 10
Antonio Márquez 2 8
Lucas Podolski 3 9
… … … …

Banquillo:

Nombre Apellidos Posicion Calidad
Raúl López 0 9

No Convocados:
Nombre Apellidos Posicion Calidad
Ronaldo Nazairo -1 5

Esta vista está basada en el scaffold por defecto que Rails crea pero
modificada un poco usando un partial (Si necesetaís que ponga el código
de mis vistas y controladores decídmelo). Mi idea para hacer el cambio
es tener dos columnas que permitan seleccionar a dos jugadores para
efectuar el cambio, es decir, lo siguiente:

Plantilla del Club:

Titulares:

Nombre Apellidos Posicion Calidad Cambio1 Cambio2
Carlos Belizón 1 10 *
Antonio Márquez 2 8
Lucas Podolski 3 9
… … … …

Banquillo:

Nombre Apellidos Posicion Calidad
Raúl López 0 9 *

No Convocados:
Nombre Apellidos Posicion Calidad
Ronaldo Nazairo -1 5

[Botón Cambiar]

Creo que he de transformar las tablas en formularios, pero no estoy
seguro de que esa sea la forma correcta de hacerlo. ¿Alguien me puede
echar una mano?

Por si acaso pongo aquí el controlador así como las vistas:

clubs_controller.rb:

def plantilla
@club = Club.find(params[:id])
@titulares = @club.jugadores.titulares
@suplentes = @club.jugadores.suplentes
@no_convocados = @club.jugadores.no_convocados

respond_to do |format|
  format.html
  format.xml{render :xml => [@titulares, @suplentes, 

@no_convocados]}
end
end

plantilla.html.haml:

%h1= "Listado de Jugadores del " + h(@club.nombre)
%h2 Titulares
=render_partial(‘jugadores/listado’, @titulares)
%h2 Suplentes
=render_partial(‘jugadores/listado’, @suplentes)
%h2 No convocados
=render_partial(‘jugadores/listado’, @no_convocados)

_listado.html.haml:
%table
%tr
%th Nombre
%th Apellidos
%th Equipo
%th Velocidad
%th Resistencia
%th Regate
%th Robo
%th Pase
%th Tiro
%th Portero
%th Calidad
%th Edad
%th Sueldo
%th Claúsula

  • for jugador in listado
    %tr
    %td= h jugador.nombre
    %td= h jugador.apellidos
    %td= h equipo_del_jugador(jugador)
    %td= h jugador.velocidad
    %td= h jugador.resistencia
    %td= h jugador.regate
    %td= h jugador.robo
    %td= h jugador.pase
    %td= h jugador.tiro
    %td= h jugador.portero
    %td= h jugador.calidad
    %td= h jugador.edad
    %td= h jugador.sueldo
    %td= h jugador.clausula
    %td= radio_button(“jugador”, “cambio1”, jugador) #Selección del
    primer jugador
    %td= radio_button(“jugador”, “cambio2”, jugador) #Selección del
    segundo jugador
    %br

Mi idea es crear una nueva acción llamada cambiar en mi controlador
ClubsController que realice el cambio, pero mi duda es: ¿Cómo capturo
los valore seleccionados en los radio_buttons?

He conseguido prácticamente solucionar mi problema de esta forma:

ClubsController.rb:

def cambiar
if params[:jugador].nil?
redirect_to(plantilla_club_path)
else
@jugador1 = Jugador.find_by_id(params[:jugador][:cambio1])
@jugador2 = Jugador.find_by_id(params[:jugador][:cambio2])
@jugador1.cambiar_por(@jugador2)
@jugador1.save
@jugador2.save

  respond_to do |format|
    format.html {redirect_to(plantilla_club_path)}
    format.xml {render :xml => [@titulares, @suplentes, 

@no_convocados]}
end
end
end

plantilla.html.haml:

  • form_for :cambio, :url => cambiar_club_path(@club) do |f|
    %h1= "Listado de Jugadores del " + h(@club.nombre)
    %h2 Titulares
    =render_partial(‘jugadores/listado’, @titulares)
    %h2 Suplentes
    =render_partial(‘jugadores/listado’, @suplentes)
    %h2 No convocados
    =render_partial(‘jugadores/listado’, @no_convocados)
    =f.submit ‘Cambiar’

_listado.html.haml:

%table
%tr
%th Nombre
%th Apellidos
%th Equipo
%th Velocidad
%th Resistencia
%th Regate
%th Robo
%th Pase
%th Tiro
%th Portero
%th Calidad
%th Edad
%th Sueldo
%th Claúsula

  • for jugador in listado
    %tr
    %td= h jugador.nombre
    %td= h jugador.apellidos
    %td= h equipo_del_jugador(jugador)
    %td= h jugador.velocidad
    %td= h jugador.resistencia
    %td= h jugador.regate
    %td= h jugador.robo
    %td= h jugador.pase
    %td= h jugador.tiro
    %td= h jugador.portero
    %td= h jugador.calidad
    %td= h jugador.edad
    %td= h jugador.sueldo
    %td= h jugador.clausula
    %td= radio_button(“jugador”, “cambio1”, jugador.id)
    %td= radio_button(“jugador”, “cambio2”, jugador.id)
    %br

Pero tengo el siguiente problema: Si alguien selecciona un radio button
y el otro no me lanza la siguiente excepción:

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.posicion

¿Cómo puedo solucionar esto?

Jose Antonio P. wrote:

def cambiar
if params[:jugador].nil?
redirect_to(plantilla_club_path)
else
begin
@jugador1 = Jugador.find_by_id(params[:jugador][:cambio1])
@jugador2 = Jugador.find_by_id(params[:jugador][:cambio2])
@jugador1.cambiar_por(@jugador2)
@jugador1.save
@jugador2.save
rescue Exception => e
flash[:error] = “No ha seleccionado dos jugadores”
end

  respond_to do |format|
    format.html {redirect_to(plantilla_club_path)}
    format.xml {render :xml => [@titulares, @suplentes,

@no_convocados]}
end
end
end

Esa podria ser una solucion.

Muchas gracias he dejado el código mejor así:

def cambiar
begin
@jugador1 = Jugador.find_by_id(params[:jugador][:cambio1])
@jugador2 = Jugador.find_by_id(params[:jugador][:cambio2])
@jugador1.cambiar_por(@jugador2)
@jugador1.save
@jugador2.save
rescue Exception => e
flash[:error] = “No ha seleccionado los jugadores a cambiar”
end
respond_to do |format|
format.html {redirect_to(plantilla_club_path)}
format.xml {render :xml => [@titulares, @suplentes,
@no_convocados]}
end
end

Ahora me surje una duda más, quiero Añadirle JS no intrusivo a la web de
tal forma que para hacer un cambio simplemente tenga que hacer click en
un jugador y hacer click en otro (Por tanto quiero que desaparezcan los
radio buttons y el boton de cambio en caso de tener JavaScript
disponible). Lo pienso hacer con JQuery ya que me gusta más para poder
realizar scripts no intrusivos. A groso modo: ¿Es correcto ocultar los
radio_buttons y el button cuando mi árbol DOM esté cargado?

Pero tengo el siguiente problema: Si alguien selecciona un radio button
y el otro no me lanza la siguiente excepción:

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.posicion

¿Cómo puedo solucionar esto?

Puedes capturar la excepcion en el controlador, o puedes comprobar los
parametros, para que cuando uno de ellos sea nil, redireccione a la
pagina con un mensaje flash, por ejemplo.

def cambiar
if params[:jugador].nil?
redirect_to(plantilla_club_path)
else
begin
@jugador1 = Jugador.find_by_id(params[:jugador][:cambio1])
@jugador2 = Jugador.find_by_id(params[:jugador][:cambio2])
@jugador1.cambiar_por(@jugador2)
@jugador1.save
@jugador2.save
rescue Exception => e
flash[:error] = “No ha seleccionado dos jugadores”
end

  respond_to do |format|
    format.html {redirect_to(plantilla_club_path)}
    format.xml {render :xml => [@titulares, @suplentes,

@no_convocados]}
end
end
end

Esa podria ser una solucion.