Creando una sencilla Plataforma de Blogs - Las Publicaciones
Por: Lukasz Muzyka, en:
ES:This tutorial assumes you have already completed:
- Install Ruby on Rails
- Create Ruby on Rails application
- Create Static Pages - without this deploy will not work
- Install Git
- Create Remote Git Repository - optional but recommended
- Deploy application to Heroku
- Manage users with Devise
- How to add Twitter Bootstrap to Ruby on Rails application - Advised
- Creating Simple Blogging Platform - Creating Model
- Creating Simple Blogging Platform - Routes
- Creating Simple Blogging Platform - Displaying Posts
Ahora que tenemos una manera de mostrar las publicaciones, podemos seguir adelante y comenzar a crearlas usando formularios.
Paso 1: Crea la acción "New"
Empezaremos añadiendo una "nueva" acción a nuestro controlador:
/app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
def show
@post = Post.find(params[:id])
end
def new
end
end
Paso 1.2: "instancia" Post en controlador
Esta vez dentro de la acción "instanciaremos" la nueva publicación y la guardaremos como variable. Al igual que lo hicimos antes en la línea de comandos:
/app/controllers/posts_controller.rb
def new
@post = Post.new
end
Paso 1.3: Crea un nuevo archivo de HTML
Ahora podemos proceder con la creación de una plantilla para nuevas publicaciones. Dentro de /app/views/posts/
crea un nuevo archivo llamado "new.html.erb" y en el, agrega el siguiente código:
/app/views/posts/new.html.erb
<%= form_for @post do |f| %>
<div class="form-group">
<%= f.label :title, class: 'control-label' %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :body, class: 'control-label' %>
<%= f.text_area :body, class: 'form-control', rows: 6 %>
</div>
<%= f.submit 'Save', class: 'btn btn-primary' %>
<% end %>
Paso 1.4: Añade el Enlace
Pongamos el enlace a esta página en nuestro índice.
/app/views/posts/index.html.erb
<h1>This is a list of posts</h1>
<%= link_to 'New Post', new_post_path %>
<ul>
<% @posts.each do |p| %>
<li>
<h3><%= link_to p.title, post_path(p.id) %></h3>
<p><%= p.body %></p>
</li>
<% end %>
</ul>
Ahora podemos navegar a la página. Si intentas enviar el formulario, este se colgara ya que tratara de publicar datos para "crear" una acción que no hemos creamos.
Paso 2: Crea una Acción
Abre
posts_controller.rb
y copia el código de la línea 16 a la línea 30:
/app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
def show
@post = Post.find(params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(allowed_params)
if @post.save
flash[:success] = "Created new post"
redirect_to @post
else
render 'new'
end
end
private
def allowed_params
params.require(:post).permit(:title, :body)
end
end
Escribimos bastante código en unas cuantas líneas. Primero, observa el código bajo la declaración private
(todo lo que está en private, sólo está disponible dentro del controlador – una función de seguridad). Aquí definimos allowed_params
. Esta es una característica que viene con Rails 4 como estándar de seguridad mejorada. No iremos ahora en detalles de por qué esta hecho así. Lo que tienes que recordar es que tienes que añadir todos los parámetros que están incluidos en el formulario de "permitted". De lo contrario, no se salvaron después de enviarlo.
Ahora, veamos la acción. En la primera línea se puede ver:
@post = Post.new(allowed_params)
Creamos la variable @post
y estamos utilizando el metodo new
en la clase Post
. Pasamos como argumentos allowed_params
el cual hemos definido bajo la declaración privada.
El método new
no guarda nuestra publicación en la base de datos. En cambio, almacena la publicación en su memoria hasta que decidimos guardarla. Eso, lo haremos en el siguiente paso. Si no podemos guardarla, @post.save
se devolverá a falso y la acción reenviara una "nueva" página, si la acción lo logra, recibiremos una notificación de que tuvimos éxito y la acción mostrara la página que nos dirigirá a @post
.
¿Por qué no se podría guardar? Quizás el título o el cuerpo estaban vacíos.
Por el momento no tenemos manera de rechazar ese tipo de envíos. Puedes intentarlo; nuestra aplicación salvará cualquier tipo de registro en este punto. Sin ningún cuerpo o título. Esto no es bueno, así que tenemos que arreglarlo.
Paso 2.2: Agrega Validations en modelo
En este punto, vuelve a nuestro modelo y añade algunas validaciones en él.
/app/models/post.rb
class Post < ActiveRecord::Base
validates :title, presence: true, length: { minimum: 3 }
validates :body, presence: true, length: { minimum: 30 }
end
Esto se asegurará de que tanto el título y el cuerpo que estén presentes tengan por lo menos 3 y 30 caracteres respectivamente.
Paso 2.3: Crea nuevos archivos
Ahora, necesitamos asegurarnos de que nuestros usuarios obtendrán notificaciones acerca de los errores, si hay alguno. Para ello, necesitamos construir un mecanismo para mostrar mensajes de error en el formulario. Dentro de /app/views
create new folder and call it "shared". Dentro de esa carpeta, crea un nuevo archivo y llámalo "_error_messages.html.erb". Asegúrate de agregar "_" al principio del nombre del archivo. En el nuevo archivo, copia y pega el siguiente código:
/app/views/shared/_error_messages.html.erb
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<p><strong>This form contains <%= pluralize(object.errors.count, 'errors') %>.</strong></p>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
Ahora, podemos volver a nuestro formulario y procesar este "parcial" allí. El código es construido de una manera en que el contenedor de errores sólo aparecerá si se produce un error.
/app/views/posts/new.html.erb
<%= form_for @post do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :title, class: 'control-label' %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group>
<%= f.label :body, class: 'control-label' %>
<%= f.text_area :body, class: 'form-control', rows: 6 %>
</div>
<%= f.submit 'Save', class: 'btn btn-primary' %>
<% end %>
Inténtalo.
Paso 3: Propiedad de Publicación
El único problema con la configuración anterior es que no hay manera para registrar quien es el autor de la publicación. Ahora cualquiera puede venir a nuestro sitio web y postear incluso cuando ellos no han iniciado su sesión. Esto obviamente no es el comportamiento que estamos buscando. Queremos que los usuarios crean una cuenta primero para poder publicar. Además, para cada entrada, queremos mostrar quién es el autor.
Para hacer referencia a usuarios en el registro de publicaciones, necesitamos agregar una nueva columna a la tabla de mensajes en la base de datos. Esto puede hacerse fácilmente con el generador de Rails para las migraciones. En bash (ventana de terminal):
bash
$ rails generate migration add_user_id_to_posts user_id:integer
Observa cómo pasamos los argumentos al generador - user_id:integer
. Rails también recogerá el nombre de la tabla y lo modificara a posts
.
invoke active_record
create db/migrate/20140512101508_add_user_id_to_posts.rb
Echémosle un vistazo el archivo recién creado en migración
db/migrate/20140512101508_add_user_id_to_posts.rb
class AddUserIdToPosts < ActiveRecord::Migration
def change
add_column :posts, :user_id, :integer
end
end
Paso 3.2: Ejecuta Migración
Ahora podemos migrar la base de datos con rake task:
bash
$ rake db:migrate
== 20140512101508 AddUserIdToPosts: migrating =================================
-- add_column(:posts, :user_id, :integer)
-> 0.0047s
== 20140512101508 AddUserIdToPosts: migrated (0.0048s) ========================
Paso 3.3: Modifica la Publicación y los Archivos de los Usuarios
Ahora, tenemos que saber acerca de la relación existente entre las publicaciones y los usuarios de nuestra aplicación. Añade la línea 4 después de class User < ActiveRecord::Base
.
app/models/user.rb
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
Ahora, agrega la línea 4 en post.rb
:
app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
validates :title, presence: true, length: { minimum: 3 }
validates :body, presence: true, length: { minimum: 30 }
end
Esas dos líneas has_many
y belongs_to
nos dan capacidad para crear mensajes "a través del" usuario que automáticamente se inyectará a user_id
en el registro de entradas. Para ver como funciona esto, cambia posts controllers
para tomar ventaja de este:
app/controllers/posts_controller.rb
def create
@user = current_user
@post = @user.posts.build(allowed_params)
if @post.save
flash[:success] = "Created new post"
redirect_to @post
else
render 'new'
end
end
Y también añade el autor a nuestros “views”:
app/views/posts/index.html
<ul>
<% @posts.each do |p| %>
<li>
<h3><%= link_to p.title, post_path(p.id) %></h3>
<p><small><strong>By: </strong><%= p.user.email %></small></p>
<p><%= p.body %></p>
</li>
<% end %>
</ul>
app/views/posts/show.html
<h1><%= @post.title %></h1>
<p><small><strong>By: </strong><%= @post.user.email %></small></p>
<p><%= @post.body %></p>
Paso 4: Ejecuta "Rails Console"
Si intentas recargar la página, verás que se cuelga. Eso es porque los puestos que hemos creado antes no contienen ningún user_id. Así que tenemos que limpiar la base de datos. Abre rails console en la terminal:
bash
$ rails console
2.1.1 :001 > Post.destroy_all
Paso 5: Usa Devise
Antes de empezar a crear las publicaciones, tenemos que hacer un último ajuste. En este momento, estamos usando current_user
para crear las publicaciones. Como ya hemos aprendimos current_user
solo se presenta si el usuario está en la sesión. ¿Qué pasa si el usuario no está en la sesión y quiere enviar una nueva publicación? La publicación se colgara. Afortunadamente, es fácil de resolver este problema usando Device.
app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_filter :authenticate_user!, except: [:show, :index]
# existing code
end
:authenticate_user!
es un método suministrado por Devise. Este permitirá que solo los usuarios que están dentro de la sesión, tengan acceso a todas las acciones, excepto las que especificamos con except
. Pero, eso no es todo. Si el usuario intenta tener acceso a una acción restringida, Devise lo enviara directamente a la página de inicio de sesión. Después de iniciar la sesión o registrarse, Devise lo llevara de regreso al lugar donde quería acceder.
¡Inténtalo!
Comentar
Tú puedes Inicio de sesión Comentar