
Esta es una aplicación basada en un scaffold, sin embargo el CRUD está modificado para responder a peticiones Ajax en Rails.Comencemos con el paso a paso! la app la he llamado “My Concerts Wishlist”
demo: http://myconcertwishlist.herokuapp.com
Creando el Proyecto wishlist.
Abres un Terminal y escribes:
$ rails new wishlist
Acceder a la carpeta “wishlist” desde el terminal:
$ cd wishlist
Creando el Scaffold: Band.
$ rails generate scaffold Band name:string fanlevel:integer description:string image:string
Ejecutamos en el terminal:
$ rake db:migrate
Analizando bands_controller.rb y el método “respond_to”
Cuando generamos el scaffold, abrimos el archivo app/controllers/bands_controller.rb y revisamos el método new, vas a ver un código autogenerado con el método “respond_to”. (lo mismo tiene el método update,destroy).
El método Respond_to es una manera de decirle a tu controlador cómo responder a diferentes tipos de peticiones. Por ejemplo, si queremos que nuestro controller “responda a” peticiones ajax agregamos a la lista la línea format.js
respond_to do |format| format.js end
Estructura de la App.
1. Creando el menú superior.
para esto crearemos una vista parcial en views/layouts/_navbar.html.erb y escribimos el ya clásico navBar de bootstrap pero en el <ul> añadimos este bloque de código. Si se fijan en la línea 4 agregamos al Helper link_to, la propiedad :remote => true, lo que permitirá cargar contenido ajax.
... ... <ul class="nav navbar-nav"> <li class="active"> <%= link_to 'Add Band', new_band_path, :remote => true, :id => "new-band-link" %> </li> </ul> ... ...
no olvidar! hacer en views\layouts\application.html.erb la llamada a la vista parcial del navBar:
<%= render 'layouts/navbar' %> <%= yield %>
2. Estructura de la vista index.html.erb
Vamos a borrar todo el código autogenerado en la vista index.html.erb y vamos a pegar este bloque de código, que dibujará en pantalla la lista de bandas. Usaremos el framework Bootstrap 3 para armar el layout. (pega antes de </head> los links de bootstrap cdn aquí)
<div id="bands" class="container-fluid" > <div class="row"> <% if @bands.blank? %> <h1 class="text-info text-center">Tu Wishlist está vacia! </h1> <% else %> <% @bands.each do |band| %> <%= render "band", :band => band %> <% end %> <% end %> </div> </div> <div id="boxShow" ></div>
Por cada iteración del Loop del objeto @bands, vamos a hacer un “render” de cada ítem, para lo cual creamos una vista parcial para organizar mejor las cosas. Vean que tenemos :remote => true en cada botón “show”/”edit”/”delete”. (img referencia!)
Vista parcial en views/bands/_band.html.erb
<div id="band_<%= band.id %>" class="item col-xs-12 col-sm-3 col-md-3 col-lg-2" style=" margin:0 auto; position:relative; float:left"> <div class="thumbnail"> <div class="caption"> <h3 class="text-left"><%= band.name.truncate(27, separator: /\s/) %></h3> <span class="small"> <% if band.fanlevel != "" %> <% for i in 1..band.fanlevel %> <span class="glyphicon glyphicon-heart pull-left " aria-hidden="true"></span> <% end %> <% end%> </span> <div class="clearfix"></div> <p class="small text-right"><span class="small text-right"> <%= link_to ' ', band, :remote => true, :class => 'showlink btn btn-default btn-sm glyphicon glyphicon-search' %></span> <span class="small text-right"> <%= link_to ' ', edit_band_path(band), :remote => true, :class => ' btn btn-default btn-sm glyphicon glyphicon-pencil' %></span> <span class="small text-right"> <%= link_to ' ', band, method: :delete, data: { confirm: 'Are you sure?' }, :remote => true, :class => 'small btn btn-default btn-sm glyphicon glyphicon-trash' %></span> </p> </div> </div> </div>
3. Creando el archivo javascript new.js.erb.
Creas un nuevo javascript en views/bands/new.js.erb
Desde ahora veremos en las vistas de extensión .js.erb cosas como “j” y “render“. la “j” es un alias del método escape_javascript y ayuda a “bloquear” retornos de carro, comillas simples/dobles que pueda tener tu vista parcial. luego viene render que dibuja una vista parcial. Por si acaso…todo lo que vemos entre <% … %> es porque es código ruby.
$('#new-band-link').hide().after('<%= j render("form") %>');
luego crea una vista parcial views/bands/_form.html.erb
Este código dibujará el formulario por donde ingresamos/editamos bandas. Es importante que el helper form_for tenga la propiedad :remote => true para permitir contenido remoto ajax (img referencia)
<div class="col-lg-12 pull-left" id="box"> <%= form_for(@band, :remote => true) do |f| %> <% if @band.errors.any? %> <div id="error_explanation"> <h2>campos requeridos!</h2> </div> <% end %> <div class="col-lg-12 pull-right"> <div class="field"> <button id="btncerrar" class="btn btn-warning pull-right" type="button" >x</button> </div><br> </div> <div class="field small"> <span class="text-danger small pull-left">(*)</span> Quiero ir al concierto de: <br> <%= f.text_field :name, class:'form-control' %> </div> <div class="field small"> <span class="text-danger small">(*)</span>Cuan Fan eres de 1 a 7<br> <%= f.number_field :fanlevel, class:'form-control' %> </div> <div class="field small"> <span class="text-danger small">(*)</span> Breve Comentario <br> <%= f.text_field :description, class:'form-control' %> </div> <div class="field small"> <span class="text-danger small">(*)</span>Foto Banda (externa) <br> <%= f.text_field :image, class:'form-control' %> </div> <div class="actions"> <%= f.submit 'agregar', :class => 'btn btn-success pull-right ' %> <span class="text-danger small">(*) campos requeridos</span> </div> <% end %> </div>
ahora abres controllers/bands_controller.rb en su método new escribimos las líneas de código más abajo.
Entonces cuando enviamos una petición para agregar un nuevo item, el controller devuelve una “respuesta” llamando específicamente a la vista new.js.erb.
# GET /bands/new def new @band = Band.new respond_to do |format| format.js end end
4. Creando el archivo javascript create.js.erb.
Luego de presionar el botón “agregar”, hacemos otro request al controller. En esta porción de código vemos que render tiene 2 parámetros, el primero es “band” que corresponde a la vista parcial “_band.html.erb” y el segundo corresponde al objeto @band que se comunicará con el model Band y asi podremos cargar la totalidad de registros de la base de datos, los cuales dibujaremos dentro de div #bands.
crea un nuevo javascript en views/bands/create.js.erb
<% if @band.errors.count == 0 %> $('#box').remove(); $('#new-band-link').show(); $('#bands .row').append('<%= j render("band", :band => @band) %>'); <% else %> $('#box').remove(); $('#new-band-link').after('<%= j render("form") %>'); <% end %>
y en el bands_controller.rb en su método create escribimos:
def create @band = Band.new(band_params) respond_to do |format| if @band.save format.js else format.js end end end
5. Creando el archivo Javascript show.js.erb
Crea un nuevo javascript en views/bands/show.js.erb
Para mostrar cada item con más elegancia…agregaremos un efecto fadeIn en jquery para que aparezca el render de la vista parcial _show.html.erb (img referencia)
$('#boxShow').empty(); $('#boxShow').fadeIn("slow").append('<%= j render("show") %>');
inmediatamente después, creas otro archivo más para la vista Parcial views/bands/_show.html.erb
Nos ayudamos de bootstrap 3 para crear el contenedor.
<div class="container"> <div class="col-lg-12 pull-right"> <div class="field"> <%= link_to 'x', bands_path, :class => "btn btn-sm btn-info pull-right" %> </div> </div> <div class="jumbotron"> <p class="text-center"> <%= image_tag(@band.image, class:"img-thumbnail") %> </p> <h1> <%= @band.name %></h1> <p class="lead"> <%= @band.description %></p> <p class="text-center"> Grado de fanatísmo:</p> <p class="text-center"> <span class="text-center"> <% for i in 1..@band.fanlevel %> <span class="glyphicon glyphicon-heart" aria-hidden="true"></span> <% end %> </span> </p> </div>
y en el bands_controller.rb en su método show escribimos el siguiente código. ¿Pero por qué? Porque queremos que al enviar una petición para “mostrar” una banda, el método “show” del controller responda invocando a views/show.js.erb y no a show.html.erb
def show respond_to do |format| format.js end end
6. Edit & Destroy lo dejo en el Repo de github
Tarea para la casa la creación de edit.js.erb y destroy.js.erb pero! puedes revisar desde el github el código fuente que comparto con ustedes, si seguíste la secuencia de new y create, verás similitudes en la lógica.
Bonus track!
Para alegrar el ejercicio con lindos colores, agregué un jquery que hace que cambien de color los div con la clase .item
Si quieres compartir tu gitHub con una versión 2.0 de mi propuesta, bienvenido sea! Puedes agregar un Buscador por ejemplo…o agregar una relación “one to many” entre bandas y estilos musicales o paises.
Que tengan un 2015 full de aprendizaje y desafíos profesionales 🙂

- Friendly URL en Rails - March 8, 2015
- Borrar un Scaffold en Ruby on Rails - January 24, 2015
- “My Concerts Wishlist” ajax scaffold Ruby on Rails - January 1, 2015
- StreetmusicMap parte 2: Integración Gmaps4Rails - December 12, 2014
- StreetmusicMap parte 1: Combobox uno a muchos en Ruby on Rails - December 11, 2014
- Twitter Search API + Ruby on Rails (II parte) - September 24, 2014
- Twitter Search API + Ruby on Rails - September 24, 2014
- SSL error: Certificate Verify Failed - September 18, 2014
Leave a Reply