Monthly Archives: June 2012

acciones custom en Rails 3 (Parte 2 editar multiples registros)

Como lo habia prometido, esta es la ultima parte de mi post sobre multiples acciones en Rails 3. En el post anterior explicaba como poder borrar multiples registros, ahora explicaré como poder editar multiples registros, sin perder la funcionalidad de borrar varios registros, estuve buscando una solución sencilla y muchas usaban trucos con javascript, pero como buen Javero me es dificil estar haciendo trucos o soluciones en el cliente haha, así que implementé algo parecido a un dispatchEvent pero mucho muy básico.

1.- Editar el archivo routes.rb

Bueno aqui tuve que simplificarme las cosas un poco y modifique la ruta existente para borrar registros y crear la nueva ruta.

    
namespace :admin do |admin|
resources :users do
collection do
post 'edit_selected'
post 'evt_dispatch', :as => "evt_dispatch"
put :update_multiple
end
end
end

Como pueden ver es necesario crear una ruta con el método put para realizar la actualización.

2.- Editar el controlador de usuarios para agregar las nuevas acciones
Mi controlador de usuarios quedó de la siguiente manera, (solo muestro las acciones modificadas o necesarias para este post):

  
def edit_selected
@users = User.find(params[:user_ids])
end

def update_multiple
@users = User.find(params[:user_ids])
@users.each do |user|
user.update_attributes!(params[:user].reject { |k,v| v.blank? })
end
flash[:notice] = "Users Updated!"
redirect_to admin_users_path
end

def evt_dispatch
if !(params[:user_ids] == nil)

case params[:button]
when "delete"
del_selected

when "edit"
@users = User.find(params[:user_ids])
render :action => "edit_selected"
end

else
redirect_to admin_users_path, :notice => "Please select at least one user."
end
end

def del_selected

if !(params[:user_ids] == nil)

params[:user_ids].each do |id|
User.delete_all(["id = ?" , id.to_i])
end
flash[:notice] = "Users deleted successfully."
redirect_to admin_users_path

else
redirect_to admin_users_path, :notice => "Please select users to delete."
end
end

Aqui se pueden observar varias cosas, primero que tengo repetida la funcionalidad en la acción edit_selected y en el evento editar de evt_dispatch, esto es porque todavia mi código sigue en fase de pruebas, y ademas que no se ejecuta la acción edit_selected inmediatamente, primero se muestra la pantalla, aqui es donde extraño un poco el ciclo de vida de JSF (Java Server Faces)… :(, también notar que la acción update_multiple esta programada para que no tome en cuenta los registros en blanco para realizar la actualización.

Otro detalle importante de recalcar es que estoy haciendo validaciones sobre si se seleccionaron registros en el servidor y no con javascript, bueno recuerden que estoy aprendiendo a usar rails y todavia no empiezo a ver como hacer esto mas dinamico con AJAX, así que sean pacientes 🙂

3.- Editando el formulario principal
Una vez configurados las rutas y el controlador, hay que agregar las acciones a los botones correspondientes, así pues mi archivo index.html.erb queda así:

   

Users catalog


<% if @users.blank? %>

The are no users yet!


<% else %>
<%= form_tag evt_dispatch_admin_users_path do %>
<%= button_tag 'Delete Selected', :value => "delete", :type => :submit, :confirm => 'Are you sure?' %>
<%= button_tag 'Edit Selected', :value => "edit", :type => :submit %>










<% @users.each do |user| %>











<% end %>
Username Name Last name Email Role Status
<%= check_box_tag "user_ids[]", user.id %> <%= user.username %> <%= user.name %> <%= user.last_name %> <%= user.email %> <%= @roles[user.role] %> <%= @status_desc[user.status.to_sym] %> <%= link_to 'Edit', edit_admin_user_path(user) %> <%= link_to 'Delete', admin_user_path(user), :method => :delete,
:confirm => 'Are you sure?' %>

<% end %>
<% end %>


<%= link_to 'New User', new_admin_user_path %>

Aquí como pueden ver uso los helpers button_tag y lo único que cambio es el “valor” del botón o lo que envia, al hacer clic a un botón se envia a la acción evt_dispatch en el controller y dependiendo de que botón se presionó entonces se ejecuta una acción.

4.- Crear vista para edición multiple
Por ultimo es necesario crear la vista para edición multiple, el archivo edit_selected.html.erb me quedó de la siguiente manera:

 
<%= form_for :user, :url => update_multiple_admin_users_path, :method => :put do |f| %>

    <% for user in @users %>

  • <%= hidden_field_tag "user_ids[]", user.id %>
    <%= user.username %>

  • <% end %>

<%= f.label :role %>
<%= f.select :role, User::roles.map{|role| [ role[1], role[0] ]}, :include_blank => true %>
<%= f.label :status %>
<%= f.select :status, User::status_desc.map{|role| [ role[1], role[0] ]}, :include_blank => true %>
<%= f.submit %>
<% end %>
<%= link_to 'Back', admin_users_path %>

Estoy usando el for para poder mostrar los elementos seleccionados para que el usuario pueda visualizar que elementos se está editando, y además estoy agregando campos en blanco para los elementos de tipo Select esto es porque quiero que los campos en blanco sean ignorados al momento de actualizar los registros. Tanto el rol como el estatus son obtenidos de un pequeño hash que agregué al modelo del usuario, esto es porque son valores predefinidos y es una manera de tener mas control sobre lo que se puede agregar en los campos.
En fin, espero les pueda servir este pequeño truco y lo puedan adaptar a sus necesidades, todavia no tengo nada entregable pero en cuanto lo tenga publicaré la ruta de mi proyecto en github para que puedan usar mi código si así lo desean. Hasta pronto.

acciones custom en Rails 3 (Parte 1 borrar multiples registros)

Muchas veces necesitamos tener o realizar operaciones especiales mas allá del CRUD (Create, Read, Update and Delete) para nuestros modelos, como por ejemplo poder elimiar varios registros a la vez o editar varios registros, etc.

Estuve buscando en varios sitios como poder realizar esto, yo tenia precisamente la problematica de necesitar borrar y editar varios registros en vez de uno a la vez, por ello aqui describo los pasos que realizé para lograr mi cometido.

Primero hay que editar el archivo routes.rb
Aqui hay que crear nuestras rutas a las acciones que queremos realizar, en mi caso mi controlador de usuarios está anidado en el controlador de administrador, entonces necesitamos nuestras rutas REST para el CRUD basico y aparte nuestras acciones custom para borrar y editar varios registros, para ello describimos nuestras rutas custom dentro del bloque collection de esta manera Rails interpreta dichas rutas para manipular varios registros, así pues quedaría de la siguiente manera:

    
namespace :admin do |admin|
resources :users do
collection do
post :delete_many, :as => :delete
end
end
end

Ahora toca agregar las acciones en el controlador, para ello edito mi archivo users_controller.rb quedando así:

    
def delete_many
if !(params[:users_ids] == nil)
params[:users_ids].each do |id|
User.delete_all(["id = ?" , id.to_i])
end
flash[:notice] = "Users deleted successfully."
redirect_to admin_users_path
end
end

Y por ultimo editamos el archivo index.html.erb (la vista donde se muestran los usuarios:

    



Users catalog


<% if @users.blank? %>



The are no users yet!


<% else %>
<%= form_tag delete_admin_users_path do %>
<%= submit_tag 'Delete Selected', :confirm => 'Are you sure?' %>

<% @users.each do |user| %>

<% end %>






















Selected Username Name Last name Email Role Status
<%= check_box_tag "users_ids[]", user.id %> <%= user.username %> <%= user.name %> <%= user.last_name %> <%= user.email %> <%= @roles[user.role] %> <%= @status_desc[user.status.to_sym] %> <%= link_to 'Edit', edit_admin_user_path(user) %> <%= link_to 'Delete', admin_user_path(user), :method => :delete,
:confirm => 'Are you sure?' %>

<% end %>
<% end %>


<%= link_to 'New User', new_admin_user_path %>

Aqui destacan varias cosas, primero, estoy usando el helper form_tag en vez de form_for porque no estoy enfocando este formulario a un modelo en particular, o dicho de otra manera este formulario no realiza operaciones CRUD, solo despliega datos, así mismo estoy usando la magia de rails para encontrar la ruta de mi controlador#acción al llamar a delete_admin_users_path, si quieres ver como utilizar las rutas basta con correr “rake routes” en una consola para ver las rutas que rails ha generado y basta con agregarles el prefijo _path para que detecte a que ruta estás apuntando, segundo, para poder tener selección multiple estoy usando el helper check_box_tag cuyo nombre del componente es “user_ids[]” y se declara así porque de esta forma rails detecta los registros seleccionados y los envia al controlador como un arreglo, por ello yo itero dicho arreglo en la acción del controlador.

Bueno por lo pronto es todo, esperen la segunda y ultima parte de este post donde describo como editar varios registros a la vez, cabe señalar que estoy aprendiendo a programar en ruby y rails mientras desarrollo esta aplicación, proximamente pondré la ruta de donde puedes descargar el código fuente de mi proyecto, pues está liberado bajo licencia AGPL v3 🙂 Hasta pronto!