Module 2 Evaluation - Cómo definir nuestro modelo Book con LazyRecord
May 08, 2020
Advertencia: Pude haberme comido alguna letra o coma.
Un modelo representa una entidad de tus datos almacenados. En nuestro caso queremos almacenar los libros que el usuario agrega con LazyRecord. Entonces creamos un modelo llamado Book (models/book.rb).
# models/book.rb
require "lazyrecord"
class Book < LazyRecord
# Código
end
De acuerdo a las historias de usuario, cada Book que el usuario guarde, debe tener un estatus (status) y notas del usuario (notes). Estas deben poder leerse y modificarse luego (attr_accessor).
require "lazyrecord"
class Book < LazyRecord
attr_accessor :status, :notes
# Cuando el usuario guarde (cree) el Book, asumimos que no tiene notas
# O sea, que es un string vacío
def initialize(status:, notes: "")
@status = status
@notes = notes
end
end
Pero también debemos guardar el día o fecha en el que se guardó el Book (guardó -> creó -> instanció).
require "lazyrecord"
class Book < LazyRecord
attr_accessor :status, :notes
def initialize(status:, notes: "")
@status = status
@notes = notes
@date = Time.now
end
end
Por otra parte, necesitamos una forma de llamar los datos de la API de Google y mostrarla en las vistas, pero llamar a la API cada vez que se genera una vista es muy tedioso. Así que mejor almacenamos la info de los libros en nuestro modelo. Y de paso sobrescribimos el ID por defecto de LazyRecord con el ID del libro en la API. Con esto podremos buscar (find) el libro usando el mismo ID de la API.
require "lazyrecord"
require "http"
class Book < LazyRecord
attr_reader :id, :date, :external_data
attr_accessor :status, :notes
# Al momento de instanciarlo sobreescribimos el ID de LazyRecord
# Con el ID de la API de Google. El cómo obtenemos el ID
# del libro en la API depende de la aplicación
def initialize(id:, status:, notes: "")
@id = id # ID del libro que debe coincidir con la API de Google
@status = status
@notes = notes
@date = Time.now
@external_data = HTTP.headers(:accept => "application/json").get(ENDPOINT_CON_ID).parse
end
end
De esta forma la variable de instancia @external_data contiene toda la info del libro de la API de Google y lo llamamos solo cuando se instancia el libro. Para instanciarlo podemos:
id = algun_codigo_para_obtener_el_ID_del_libro
book = Book.new(id: id, status: "want to read")
El @notes por defecto está vacío, el @date es automático y el @external_data se llama por defecto con el ID que provees que debe coincidir con algun ID de los libros de la API. Con esto ya tenemos un Modelo Book que podemos instanciar y en donde podemos guardar toda la data que necesitamos.
Pero podemos mejorarlo aún mas, vamos a crearle algunos métodos de ayuda. Supongamos que tenemos el libro instanciado y queremos obtener su título, la URL de su portada, sus autores o su descripción. Podríamos extraerlo directamente de @external_data, pero sería un poco tedioso, así que crearemos algunos métodos para obtenerlos.
class Book < LazyRecord
attr_reader :id, :date
attr_accessor :status, :notes
def initialize(id:, status:, notes: "")
@id = id
@status = status
@notes = notes
@date = Time.now
@external_data = HTTP.headers(:accept => "application/json").get(ENDPOINT_CON_ID).parse
end
def img_url
@external_book['volumeInfo']['imageLinks']['thumbnail']
end
def title
@external_book['volumeInfo']['title']
end
# Curiosidad: authors devuelve un array de strings. Así que
# para mostrarlos podemos usar el método join en las vistas
def authors
@external_book['volumeInfo']['authors']
end
def description
@external_book['volumeInfo']['description']
end
end
Hasta aquí ya tenemos nuestro modelo Book, pero también necesitamos algunos libros ya almacenados en nuestra app para probar que funciona y poder mostrarlos en la vista My Books. Entonces creamos un pequeño script independiente que rellene esos libros es nuestra data. Y lo haremos desde nuestra carpeta raíz.
# book_seeder.rb
require_relative "models/book"
books = [
Book.create(id: '5W6cnfQegYcC', status: 'read'),
Book.create(id: 'ntA5AlD3p4AC', status: 'read'),
Book.create(id: 'BvqcDwAAQBAJ', status: 'read'),
Book.create(id: 'JFdMAQAAIAAJ', status: 'read'),
]
Hemos usado IDs de libros que encontramos por ahí jugando con la API de Google. Con esto ya creamos y almacenamos nuestros libros y ademas los asignamos al array books. Pero para estar seguros, vamos a mostrar algunos de sus datos con p o puts.
# book_seeder.rb
require_relative "models/book"
books = [
Book.create(id: '5W6cnfQegYcC', status: 'read'),
Book.create(id: 'ntA5AlD3p4AC', status: 'read'),
Book.create(id: 'BvqcDwAAQBAJ', status: 'read'),
Book.create(id: 'JFdMAQAAIAAJ', status: 'read'),
]
books.each_with_index do |book, i|
puts "BOOK #{i + 1}"
puts "Title:"
p book.title
puts "Image:"
p book.img_url
puts "Authors:"
p book.authors
puts "Description:"
p book.description
puts "----------"
end
$ bundle exec ruby book_seeder.rb
Con esto hemos comprobado que efectivamente se crearon los libros y se almacenaron en nuestro archivo lazyrecord.pstore y podemos usarlos en nuestra aplicación.