Crea una aplicación simple de Streaming de música con Ruby on Rails
Spanish (Español) translation by Steven (you can also view the original English article)
Amazon S3 es una excelente manera de almacenar archivos, pero aprender a integrarlos en tu sitio web puede ser un desafío. En este artículo, aprenderás cómo integrar Amazon S3 y Ruby on Rails a través de la construcción de una aplicación simple para la transmisión de música.
¿Qué es y cómo funciona?
Amazon S3 es "almacenamiento para internet"
Como lo indica el sitio web de Amazon, Amazon S3 es "almacenamiento para Internet". No solo es barato, sino que también es rápido y confiable. Es una excelente manera de mostrar contenido en tu sitio web, incluidas imágenes, videos o casi cualquier cosa que desees. Amazon S3 no funciona exactamente como el almacenamiento en tu computadora, así que aquí hay algunas cosas que debe saber:
- Con Amazon S3, las carpetas se denominan "depósitos" y los archivos se denominan "objetos".
- Los cubos (Buckets) en el nivel superior se usan para determinar la URL para acceder a tus datos, por lo que solo puedes usar nombres que aún no se han tomado. Por ejemplo, si alguien ya creó un grupo de nivel superior con el nombre "videos", no puedes usar ese nombre.
- Es una buena idea tener un grupo de nivel superior con el nombre de tu sitio web, y usar subniveles de grupos para separar los archivos en diferentes secciones, como imágenes, videos o música.
Antes de que comencemos...
Antes de continuar con este tutorial, hay algunas cosas clave que deben estar en su lugar:
- El intérprete de Ruby y RubyGems instalados en tu computadora, junto con la gema Rails
- Conocimiento de (o al menos tener acceso a) tu ID de clave de acceso y Clave de acceso secreta para Amazon S3
- Una comprensión básica de Ruby on Rails
Lo que estaremos construyendo


El producto final de este tutorial es una sencilla aplicación de transmisión y descarga de música. En esta aplicación, el usuario podrá hacer lo siguiente:
- Ver una lista de toda la música cargada actualmente y subir la música ellos mismos
- Descargar la música de varias maneras, incluyendo transmitirla con audio HTML5, descargarla a través de HTTP o descargarla a través de un archivo .torrent
En el momento en que completes esta aplicación, habrás aprendido todos los temas principales que necesitas saber sobre el uso de Amazon S3 en tu aplicación Ruby on Rails.
¡Empecemos!
La gema aws-s3 te permite interactuar con el servicio Amazon S3 en tu aplicación.
Lo primero que debes hacer es instalar la gema de ruby aws-s3. La gema te permite interactuar con el servicio Amazon S3 en tu aplicación. Para hacer esto, si estás en Windows, simplemente ejecuta el comando:
1 |
gem install aws-s3 |
Después de que se instale, genera nuestra aplicación Rails con el siguiente comando:
1 |
rails new mp3app |
El último paso para iniciar tu aplicación es ir al directorio mp3app/public y eliminar el archivo llamado "index.html". Una vez que se haya completado, su aplicación está lista para comenzar a interactuar con Amazon S3.


Iniciar sesión en Amazon S3
Tu ID de clave de acceso y Clave de acceso secreta te permiten conectarse a Amazon S3.
Para que podamos interactuar con Amazon S3, debemos decirle a nuestra aplicación cómo iniciar sesión en Amazon S3. Aquí es donde tu ID de clave de acceso y Clave de acceso secreta son útiles. Tu ID de clave de acceso y Clave de acceso secreta te permiten conectarte a Amazon S3. Pero primero, debemos decirle a nuestra aplicación que estamos usando la gema aws-s3. Hacemos esto en el Gemfile:
1 |
gem 'aws-s3', :require => 'aws/s3' |
Para que nuestra aplicación realmente use esa gema, deberás escribir command bundle install. Ahora que está funcionando, debemos decirle a nuestra aplicación cómo iniciar sesión en Amazon S3. También lo hacemos en el archivo config/application.rb, en una nueva línea dentro de la clase Application:
1 |
AWS::S3::Base.establish_connection!( |
2 |
:access_key_id => 'Put your Access Key ID here', |
3 |
:secret_access_key => 'Put your Secret Access Key here' |
4 |
)
|
Este código le dice a nuestra aplicación que cree una conexión a Amazon S3 tan pronto como se inicie la aplicación (el archivo application.rb se carga cuando se inicia la aplicación). Una última cosa que debe agregarse al archivo de la aplicación es una constante con el valor del depósito que usaremos. La razón para hacer esto es que si alguna vez necesitamos cambiar el grupo que estamos usando, solo se debe actualizar en esta ubicación. Debería verse algo como esto:
1 |
BUCKET='s3tutorialmusic' |
Para este tutorial, decidí darle un nombre al grupo s3tutorialmusic, pero deberías reemplazarlo con cualquier bucket que tengas en tu cuenta. Al final, tu archivo debería tener este aspecto (pero con tu propia información de inicio de sesión):
1 |
require File.expand_path('../boot', __FILE__) |
2 |
|
3 |
require 'rails/all' |
4 |
|
5 |
Bundler.require(:default, Rails.env) if defined?(Bundler) |
6 |
|
7 |
module Mp3app |
8 |
class Application < Rails::Application |
9 |
config.encoding = "utf-8" |
10 |
config.filter_parameters += [:password] |
11 |
|
12 |
AWS::S3::Base.establish_connection!( |
13 |
:access_key_id => 'Put your Access Key ID Here', |
14 |
:secret_access_key => 'Put your Secred Access Key here' |
15 |
)
|
16 |
|
17 |
BUCKET = 's3tutorialmusic' |
18 |
|
19 |
end
|
20 |
end
|
Generando el controlador
Ahora podemos comenzar a trabajar para que nuestra aplicación muestre algo en el navegador. Para empezar, vamos a generar el controlador y las vistas que necesitaremos. En total, generaremos tres acciones para nuestro controlador (a las que llamaremos canciones): index, cargar y eliminar.
- La acción index será nuestra página principal.
- La acción 'cargar' es para subir música nueva en Amazon S3, por lo que no necesitas una vista.
- Finalmente, la acción de eliminar no tendrá una vista y será responsable de eliminar la música.
Al final, la única vista que necesitaremos para esta aplicación es la vista index, ya que actuará como un panel de control central para cada acción que pueda realizar. Ahora, combinaremos todo eso en una bonita declaración de línea de comando:
1 |
rails g controller Songs index upload delete |
Una vez que haya terminado de ejecutarse, continúa y elimina las vistas generadas para cargar y eliminar, ya que no se utilizarán. ¡Vamos a escribir el código para la acción de índice!
Trabajando en el Índice Action
En la acción index, el producto terminado permitirá a los usuarios cargar música nueva y eliminar la música existente. No hay nada que deba hacerse en el archivo del controlador de esta acción para cargar música nueva, pero necesitamos una lista de las canciones actuales para que los usuarios puedan eliminarlas.
Primero, necesitamos obtener un objeto que se refiera a nuestro grupo de música (recuerda que el nombre de ese grupo se almacena en el BUCKET constante). Así es como lo hacemos:
1 |
AWS::S3::Bucket.find(BUCKET) |
Para poder utilizar los métodos disponibles en la gema aws-s3, debemos decirle al intérprete de Ruby que deseamos buscar las funciones en el espacio de nombres AWS::S3, por lo que es parte de la llamada al método. La clase Bucket contiene todos los métodos relacionados con la manipulación de cubos. Finalmente, el método find acepta un parámetro, el nombre del grupo, y devuelve un objeto que se refiere a ese grupo. Ahora que tenemos el cubo, obtengamos todos sus objetos haciendo esto:
1 |
AWS::S3::Bucket.find(BUCKET).objects |
El método objects devuelve un hash con los nombres de todos los objetos en ese cubo. Finalmente, necesitamos almacenar el resultado de esa llamada de método en una variable de instancia para que podamos usarlo en nuestra vista. Al final, así es como se verá la acción index:
1 |
def index |
2 |
@songs = AWS::S3::Bucket.find(BUCKET).objects |
3 |
end
|
Continuando con la vista Index
Ahora necesitamos hacer la vista para que el usuario cargue y borre música. Comencemos con el último y creemos una lista desordenada de todos los objetos cargados actualmente, con un enlace para eliminar ese objeto. Podemos hacerlo así:
1 |
<ul> |
2 |
<% @songs.each do |song| %> |
3 |
<li><%= song.key %> - <%= link_to "Delete", "songs/delete/?song=" + song.key, :confirm => 'Are you sure you want to delete ' + song.key + '?' %></li> |
4 |
<% end %>
|
5 |
</ul> |
- Primero, creamos una lista desordenada.
- Luego, recorramos todas las canciones de la variable
@songsutilizando cada método. - Para cada canción, creamos un elemento de la lista y construimos el texto que aparecerá para cada elemento. La primera parte es la clave de las canciones, porque cada canción es un hash, y la clave para ese hash es el nombre de la canción.
- Luego, ponemos un enlace a la acción de eliminar, donde se puede eliminar la canción. Para la url, usamos una cadena de consulta al final para indicar a la acción de eliminar qué canción se debe eliminar.
- Finalmente, tenemos un mensaje de confirmación para advertir al usuario antes de que realmente elimine la canción.
1 |
if (params[:song]) |
2 |
AWS::S3::S3Object.find(params[:song], BUCKET).delete |
3 |
redirect_to root_path |
4 |
else
|
5 |
render :text => "No song was found to delete!" |
6 |
end
|
- Primero, verificamos que el parámetro de la canción esté especificado.
- Si fue así, entonces usamos el método de búsqueda para obtener el objeto que representa esa canción.
- Finalmente, usamos el método de eliminación para eliminarlo de Amazon S3.
- Luego, debemos redirigir al usuario a una nueva página porque la acción de eliminar no tiene vista. Sin embargo, si el parámetro de la canción nunca se especificó, simplemente representamos el texto "¡No se encontró ninguna canción para eliminar!".
Dejar que el usuario cargue música
Ahora, debemos permitir que el usuario cargue música, ya que esa fue una de las piezas principales de la funcionalidad de esta aplicación. Primero, creamos un formulario simple que le permite al usuario elegir un archivo para cargar. Podemos hacerlo así:
1 |
<h2>Upload a new MP3:</h2> |
2 |
<%= form_tag upload_path, :method => "post", :multipart => true do %> |
3 |
<%= file_field_tag "mp3file" %> |
4 |
<%= submit_tag "Upload" %> |
5 |
<% end %> |
Creamos un formulario que se envía a la acción de carga, que es la acción que realmente realiza la carga a Amazon S3. Usamos post y multipart porque estamos enviando archivos. Aparte de eso, este formulario es muy simple y fácil de entender, por lo que ahora podemos pasar a implementar la parte del controlador de esta acción.
Enviar el archivo a Amazon S3
Necesitamos tomar el archivo que se envió y crear un nuevo objeto S3 para él, que se realizará en la acción de carga. Podemos hacer eso con esta línea de código:
1 |
AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, BUCKET, :access => :public_read) |
Hay mucho en esta línea de código, así que explicaré cada parte individualmente.
Como de costumbre, accedemos a AWS::S3::S3Object para interactuar con objetos en Amazon S3.
Usamos el comando store para subir archivos a S3. El primer parámetro especifica cómo llamar al archivo. Usamos el parámetro original_filename del archivo cargado para esto para que el nombre permanezca igual. En cuanto al método sanitize_filename, eso se explicará en el siguiente párrafo. El segundo parámetro son los datos reales del archivo, que se obtienen al llamar al método de lectura en el archivo cargado. El tercer parámetro especifica el grupo a usar, y el cuarto determina quién puede acceder al archivo. Como queremos que todos puedan leer el archivo (que incluye la descarga), especificamos el acceso como :public_read.
El método sanitize_filename es un método que ha sido usado por muchas personas y complementos, como attachment_fu, y se usa para resolver un problema con Internet Explorer (impactante, ¿no es así?). En lugar de simplemente darnos el nombre del archivo cuando llamamos al método original_filename, IE devuelve la ruta completa al archivo; por ejemplo, si el archivo que queríamos cargar se llamaba mysong.mp3, en su lugar nos daría C:\rails\mp3app\mysong.mp3 cuando llamamos original_filename. Podemos solucionar esto agregando el siguiente código al final del controlador:
1 |
private
|
2 |
|
3 |
def sanitize_filename(file_name) |
4 |
just_filename = File.basename(file_name) |
5 |
just_filename.sub(/[^\w\.\-]/,'_') |
6 |
end
|
Nuestro último paso para completar la acción de carga es agregar algunas verificaciones de errores y rutas. La forma en que haces la comprobación de errores en ruby es con una instrucción begin...rescue...end. Muchas cosas pueden salir mal al cargar un archivo, por lo que tener una verificación de errores evitará que el usuario vea un mensaje de error que Rails generaría automáticamente. Aquí está la versión modificada de la acción de carga:
1 |
def upload |
2 |
begin
|
3 |
AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, BUCKET, :access => :public_read) |
4 |
redirect_to root_path |
5 |
rescue
|
6 |
render :text => "Couldn't complete the upload" |
7 |
end
|
8 |
end
|
Si se produce un error, simplemente representamos un texto que se lo dice al usuario. A pesar de que el usuario sigue viendo un mensaje de error, es mejor que una enorme lista de códigos que aparecería en un mensaje de error generado por Rails.
Enrutando nuestra aplicación
Es posible que hayas notado que a lo largo del código que hemos escrito hasta ahora, ha habido muchas veces donde se ha utilizado algo como upload_path en lugar de especificar un controlador y una acción. Podemos hacer esto debido a un archivo llamado route.rb. Esto le dice a nuestra aplicación a qué URL se puede acceder en nuestra aplicación. También le damos nombres a ciertas rutas para facilitar la actualización de nuestro código. Aquí es cómo puede nombrar las rutas que utilizará nuestra Mp3app:
1 |
match "songs/upload", :as => "upload" |
2 |
match "songs/delete", :as => "delete" |
3 |
|
4 |
root :to => "songs#index" |
El método de coincidencia especifica una ruta, como songs/upload, y le da un nombre, upload_path. Ese nombre se especifica usando :as => "name" como segundo parámetro del método de coincidencia. Finalmente, el método root especifica qué acción será la acción raíz, que actúa de forma similar a index.html en un sitio web estático basado en HTML.
La acción de carga completa
Ahora, hemos terminado de implementar la funcionalidad de la acción de carga. Aquí está el código final para el archivo songs_controller.rb hasta ahora:
1 |
class SongsController < ApplicationController |
2 |
def index |
3 |
@songs = AWS::S3::Bucket.find(BUCKET).objects |
4 |
end
|
5 |
|
6 |
def upload |
7 |
begin
|
8 |
AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, BUCKET, :access => :public_read) |
9 |
redirect_to root_path |
10 |
rescue
|
11 |
render :text => "Couldn't complete the upload" |
12 |
end
|
13 |
end
|
14 |
|
15 |
def delete |
16 |
if (params[:song]) |
17 |
AWS::S3::S3Object.find(params[:song], BUCKET).delete |
18 |
redirect_to root_path |
19 |
else
|
20 |
render :text => "No song was found to delete!" |
21 |
end
|
22 |
end
|
23 |
|
24 |
private
|
25 |
|
26 |
def sanitize_filename(file_name) |
27 |
just_filename = File.basename(file_name) |
28 |
just_filename.sub(/[^\w\.\-]/,'_') |
29 |
end
|
30 |
|
31 |
end
|
Y aquí es cómo se ve la aplicación hasta ahora cuando se ve en el navegador.


Descargando la musica
Hasta ahora, nuestra aplicación ha recorrido un largo camino. El usuario ahora puede cargar música, ver una lista de la música cargada actualmente y eliminar cualquier música existente. Ahora, tenemos una última pieza de funcionalidad central para implementar. Eso es permitir que el usuario realmente descargue esta música. Como se especificó al inicio de este tutorial, el usuario puede hacerlo de tres maneras:
- Transmitirlo con audio HTML5,
- Descárgalo a través de HTTP, y
- Descargarlo utilizando un archivo torrent.
En este momento, la lista de música solo se muestra usando una lista desordenada. Sin embargo, como vamos a terminar agregando tres enlaces adicionales al final de cada línea (uno para cada método de descarga), es más factible usar una tabla para organizar la lista. Modifiquemos la vista de índice para reflejar este cambio:
1 |
<h2>Download and Delete Existing MP3's</h2> |
2 |
<table>
|
3 |
<% @songs.each do |song| %> |
4 |
<tr>
|
5 |
<td><%= song.key %></td> |
6 |
<td><%= link_to "Delete", "songs/delete/?song=" + song.key, :confirm => 'Are you sure you want to delete ' + song.key + '?' %></td> |
7 |
</tr>
|
8 |
<% end %>
|
9 |
</table>
|
- Primero, actualizamos el encabezado para reflejar que también podemos descargar la música.
- En segundo lugar, cambiamos la lista desordenada a una tabla, y ponemos el nombre de la canción y el enlace de descarga en su propio <td>.
Ahora estamos listos para agregar el código y permitir que el usuario descargue música. Comencemos con la descarga a través de HTTP, porque es la más fácil de implementar.
Descarga vía HTTP
Para descargar a través de HTTP, solo necesitamos agregar un nuevo <td> a nuestra tabla con un enlace al archivo .mp3. La gema aws-s3 tiene métodos incorporados que nos permiten generar la url para un archivo. Sin embargo, la mejor práctica es poner cualquier "método de ayuda" como estos en el archivo auxiliar para ese controlador. Debido a que estamos utilizando estos métodos en toda la aplicación (especialmente si decides extender esta aplicación por tu cuenta), los métodos de ayuda se colocarán en el archivo application_helper.rb. Aquí es cómo se obtiene la URL:
1 |
def download_url_for(song_key) |
2 |
AWS::S3::S3Object.url_for(song_key, BUCKET, :authenticated => false) |
3 |
end
|
Este método solo acepta un parámetro, que es el nombre de la canción. Para ayudarnos a recordar que se puede acceder al nombre de la canción por song.key, llamamos el parámetro song_key. Como de costumbre, accedemos a la clase AWS::S3::S3Object para interactuar con objetos de Amazon S3. El método url_for toma dos parámetros, y el tercero es opcional.
- El primero es el nombre del archivo que estás buscando.
- El segundo es el nombre del cubo donde se encuentra el archivo.
- Finalmente, el tercer parámetro se usa para darnos una URL que no caducará. Si no especificamos
:authenticated => false, todas las URL caducarán en 5 minutos (de forma predeterminada).
1 |
<td><%= link_to "Download", download_url_for(song.key) %></td> |
Este <td> va entre el nombre de la canción y el enlace de eliminación (pero eso es una preferencia personal, por lo que puedes tener los enlaces en el orden que elijas).
Descargando a través de Bit Torrent
La descarga de archivos desde Amazon S3 a través de Bit Torrent es muy similar a la descarga a través de HTTP. De hecho, la única diferencia entre las dos URL de descarga es que el torrent .torrent al final. Por lo tanto, nuestro método auxiliar para generar la URL de torrent solo agregará .torrent al final de la url de HTTP. Aquí es cómo harías eso:
1 |
def torrent_url_for(song_key) |
2 |
download_url_for(song_key) + "?torrent" |
3 |
end
|
Ahora, solo necesitamos agregar otro <td> a nuestra tabla:
1 |
<td><%= link_to "Torrent", torrent_url_for(song.key) %></td> |
Streaming con audio HTML5
Transmitir las canciones a través del audio HTML5 es un poco más difícil que solo descargar la canción, así que comencemos con la parte fácil: <td> para esto. Sin embargo, habrá algunas diferencias con respecto a los enlaces que agregamos para HTTP y Bit Torrent.
- Primero, debemos tener una forma de identificar este enlace para agregar la etiqueta <audio> a la página, por lo que le daremos una clase de html5.
- En segundo lugar, necesitamos una forma de conocer la fuente del mp3
<source>que se usará para la etiqueta, por lo que solo le daremos la misma url que la descarga HTTP. Esto también servirá como un respaldo para los navegadores con javascript deshabilitado, porque usaremos javascript para agregar la etiqueta<audio>a la página.
Aquí está el código para generar el enlace:
1 |
<td><%= link_to "HTML5 Audio", download_url_for(song.key), :class => "html5" %></td> |
Ahora debemos trabajar en el javascript para agregar la etiqueta de audio a la página cuando se haga clic en este enlace. Para hacer esto, usaremos una técnica similar a la técnica que Jeffrey Way usa en su tutorial, El elemento de Audio HTML 5. El primer paso es agregar algunas cosas a nuestros archivos de vista. En nuestro archivo layout/application.html.erb, debemos incluir la última versión de jQuery, ya que esa es la biblioteca de javascript que usaremos. Aquí está el código para agregar justo antes de la primera línea de inclusión de javascript:
1 |
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js" %> |
Luego, cambia el primer parámetro para la etiqueta de inclusión original de :defaults a application.js, porque ahí es donde almacenaremos nuestro código javascript y los otros archivos JavaScript predeterminados no serán necesarios. A continuación, debemos agregar una sección a nuestra vista index.html.erb para colocar la etiqueta de audio. En la parte superior de esa vista, debemos colocar el siguiente código:
1 |
<h2>Listen to a MP3 with HTML5 Audio</h2> |
2 |
<section id="audio"> |
3 |
</section>
|
Siguiendo con el tema HTML5, usamos una etiqueta section en lugar de un div para crear nuestra sección de audio.
Obtenemos una referencia a la sección de audio y la guardamos en una variable, lo que se considera una mejor práctica. A continuación, debemos agregar un controlador de eventos de clic a nuestros enlaces con la clase html 5. Cuando ese controlador de eventos se apaga, necesitamos hacer algunas cosas:
- Primero, necesitamos crear una nueva etiqueta de audio y asignarle algunos atributos como controles.
- Luego, debemos agregarle la etiqueta de origen para que realmente sepa qué reproducir.
- Finalmente, debemos reemplazar el HTML en la sección de audio con la nueva etiqueta de audio y devolver el valor falso para que la acción normal del enlace no se realice, lo que sería descargar la canción. Aquí es cómo se puede poner todo junto:
1 |
$(document).ready(function() { |
2 |
var audioSection = $('section#audio'); |
3 |
$('a.html5').click(function() { |
4 |
|
5 |
var audio = $('<audio>', { |
6 |
controls : 'controls' |
7 |
});
|
8 |
|
9 |
var url = $(this).attr('href'); |
10 |
$('<source>').attr('src', url).appendTo(audio); |
11 |
audioSection.html(audio); |
12 |
return false; |
13 |
});
|
14 |
});
|
Ya que este tutorial es sobre Ruby on Rails, y no JavaScript, no voy a explicar en detalle cómo funciona este código. Sin embargo, el código es bastante simple, por lo que debería ser fácil para ti averiguar. Una cosa que debes tener en cuenta es que esto solo funcionará en los navegadores compatibles con HTML5 y compatibles con mp3 como fuentes válidas para etiquetas de audio. Para la mayoría de los navegadores, la última versión admitirá este código HTML5, pero los navegadores más antiguos no lo admiten.
Vista Index completa
Finalmente hemos completado toda la funcionalidad principal para esta aplicación. El usuario puede cargar, descargar y eliminar archivos mp3 de varias formas, como audio HTML5, descargas HTTP y Bit Torrent. Aquí es cómo debe verse la vista del índice en este punto:
1 |
<h2>Listen to a MP3 with HTML5 Audio</h2> |
2 |
<section id="audio"> |
3 |
</section>
|
4 |
<h2>Upload a new MP3</h2> |
5 |
<%= form_tag upload_path, :method => "post", :multipart => true do %> |
6 |
<%= file_field_tag "mp3file" %> |
7 |
<%= submit_tag "Upload" %> |
8 |
<% end %> |
9 |
<h2>Download and Delete Existing MP3's</h2> |
10 |
<table>
|
11 |
<% @songs.each do |song| %> |
12 |
<tr>
|
13 |
<td><%= song.key %></td> |
14 |
<td><%= link_to "HTML5 Audio", download_url_for(song.key), :class => "html5" %></td> |
15 |
<td><%= link_to "Download", download_url_for(song.key) %></td> |
16 |
<td><%= link_to "Torrent", torrent_url_for(song.key) %></td> |
17 |
<td><%= link_to "Delete", "songs/delete/?song=" + song.key, :confirm => 'Are you sure you want to delete ' + song.key + '?' %></td> |
18 |
</tr>
|
19 |
<% end %>
|
20 |
</table>
|
Si aún no lo has hecho, deberías intentar ejecutar este código y probarlo por ti mismo. Puedes hacer esto ejecutando el comando: rails s. A pesar de que hemos completado la funcionalidad principal para esta aplicación, todavía hay cosas que deben hacerse, como el estilo de la página. Vamos a hacer eso ahora.
Diseño de la aplicación
Lo primero que debes hacer es envolver la página en un contenedor para que podamos centrarla. Todo lo que necesitamos hacer es colocar un div con un id de contenedor alrededor de la declaración de rendimiento en el archivo de diseño para que se vea algo como esto:
1 |
<div id="container"> |
2 |
<%= yield %> |
3 |
</div>
|
A continuación, utilizaremos el estilo de la gema Ryan Bates, nifty_generators, para darle a nuestra aplicación un estilo básico. Aquí está el CSS que usaremos de esa gema:
1 |
#container { |
2 |
width: 75%; |
3 |
margin: 0 auto; |
4 |
background-color: #FFF; |
5 |
padding: 20px 40px; |
6 |
border: solid 1px black; |
7 |
margin-top: 20px; |
8 |
}
|
9 |
body { |
10 |
background-color: #4B7399; |
11 |
font-family: Verdana, Helvetica, Arial; |
12 |
font-size: 14px; |
13 |
}
|
14 |
.clear { |
15 |
clear: both; |
16 |
height: 0; |
17 |
overflow: hidden; |
18 |
}
|
Ahora vamos a trabajar la vista index. Lo primero que debemos hacer es dividir la página en tres secciones. Esas secciones serán un encabezado, una sección principal y una barra lateral. En la parte superior de la página, vamos a agregar un encabezado simple:
1 |
<header>
|
2 |
<h1>My First Music Streaming Application</h1> |
3 |
</header>
|
A continuación, dividamos la página en una región principal y una región de barra lateral. Nuestra región principal consistirá en la lista de canciones, mientras que la barra lateral contendrá el audio HTML5 y el formulario de carga. Así es como modificaremos el código:
1 |
<div class="clear"></div> |
2 |
<section id="sidebar"> |
3 |
<h2>HTML5 Audio</h2> |
4 |
<section id="audio"> |
5 |
No song is currently playing. |
6 |
</section>
|
7 |
|
8 |
<h2>Upload a Song</h2> |
9 |
<%= form_tag upload_path, :method => "post", :multipart => true do %> |
10 |
<%= file_field_tag "mp3file" %><br /> |
11 |
<%= submit_tag "Upload" %> |
12 |
<% end %> |
13 |
</section>
|
14 |
<section id="main"> |
15 |
<h2>Download/Delete Songs</h2> |
16 |
<table>
|
17 |
<% @songs.each do |song| %> |
18 |
<tr>
|
19 |
<td><%= song.key %></td> |
20 |
<td><%= link_to "HTML5 Audio", download_url_for(song.key), :class => "html5" %></td> |
21 |
<td><%= link_to "Download", download_url_for(song.key) %></td> |
22 |
<td><%= link_to "Torrent", torrent_url_for(song.key) %></td> |
23 |
<td><%= link_to "Delete", "songs/delete/?song=" + song.key, :confirm => 'Are you sure you want to delete ' + song.key + '?' %></td> |
24 |
</tr>
|
25 |
<% end %>
|
26 |
</table>
|
27 |
</section>
|
28 |
<div class="clear"></div> |
Ya que usaremos floats para diseñar esta página, debemos limpiarlos antes y después para asegurarnos de que el diseño no se arruine. Ahora agreguemos el CSS para ajustar el diseño de esas secciones:
1 |
#sidebar { |
2 |
width: 30%; |
3 |
float: left; |
4 |
}
|
5 |
#main { |
6 |
width: 70%; |
7 |
float: left; |
8 |
}
|
9 |
a, a:visited { |
10 |
color: #00f; |
11 |
text-decoration: none; |
12 |
}
|
13 |
a:hover { |
14 |
text-decoration: underline; |
15 |
}
|
16 |
td { |
17 |
padding: 5px; |
18 |
}
|
La barra lateral será el 30% de la página y la sección principal será el 70% de la página. Además, hay CSS para eliminar el subrayado de los enlaces a menos que el mouse se desplace sobre él, y también se agrega relleno a las etiquetas <td> para que no se vea tan abarrotado. Al final, ese es realmente el único CSS que necesitamos para darle a la página un diseño básico. Siéntete libre de agregar a esta aplicación todo el estilo que desees, ya que ciertamente hay formas de hacer que esta aplicación se vea mejor.


Conclusión
Esperemos que ahora tengas una buena comprensión de cómo interactuar con Amazon S3 desde tu aplicación Ruby on Rails. Con la gema aws-s3, hacer esto es muy fácil, por lo que agregarlo a una aplicación existente tomará muy poco tiempo. Siéntete libre de modificar esta aplicación de la forma que desees para ver si puedes mejorarla de alguna manera. ¡Recuerda agregar tu propia información de inicio de sesión de Amazon S3 y tu constante del cubo al archivo application.rb, de lo contrario la aplicación no se iniciará!
Para aquellos de ustedes que son expertos en Ruby on Rails, estoy seguro de que pueden encontrar una manera de optimizar esta aplicación aún más. Además, sería genial compartir las optimizaciones que realices en la sección de comentarios para que los lectores puedan aprovechar aún más este tutorial.



