El día de hoy me encuentro estudiando más acerca de técnicas para organizar código de una manera más adecuada con las bondades que brinda Ruby On Rails.
Por lo tanto, para dar inicio solo basta un simple, problema con su solución donde tenemos un modelo Student el cual estará compuesto de las siguientes columnas:
- name
- qualifications
Empezaremos generando nuestra migración con el siguiente comando:
rails g migration CreateStudent
Esta debera de lucir como se muestra enseguida:
class CreateStudent < ActiveRecord::Migration[7.0]
def change
create_table :students do |t|
t.string :name
t.json :qualifications
t.timestamps
end
end
end
Con lo cual podremos generar objetos del tipo Student de la siguiente manera:
Student.create!(name: 'Daniel', qualifications: { subject_one: 10, subject_two: 9, subject_three: 8, subject_four: 10 })
Enseguida se nos pide que calculemos el promedio de las calificaciones y lo primero que hariamos es generar los modelos en nuestro modelo Student como se muestra enseguida:
class Student < ApplicationRecord
validates :name, presence: true
validates :qualifications, presence: true
def average_calculation
sum_qualificiations / qualifications.size
end
private
def sum_qualificiations
qualifications.values.inject(0, :+)
end
end
Con esto podremos obtener el promedio de un estudiante únicamente llamando al método average_calculation es decir:
student = Student.first
student.average_calculation #=> 9
En este caso tenemos la clase Student y está debe ser capaz de únicamente tratar con temas relacionados con el estudiante, su nombre, nombre de tutor, teléfono de emergencias, etcétera.Si bien hasta aquí podemos indicar que hemos hecho lo solicitado, estamos olvidando una regla muy importante en la POO que es la responsabilidad única en clases.
El problema
Este radica en que él hacer el calculo de calificaciones no es algo que una clase como Student debería de hacer y está logica la podemos pasar a un objeto compuesto que representara las calificaciones.
Todo esto lo podemos hacer gracias al método composed_of que brinda Ruby On Rails el cual lo que hace es delegar la responsabilidad a una clase externa.
Lo anterior es llamado composition el cual podremos definirla como una relación entre dos o más clases donde podemos adquirir un comportamiento y utilizar el código que está en otra clase en nuestro objeto actual.
La solucion
Lo que tendremos que hacer son dos cosas sencillas:
- Actualizar nuestro modelo Student
- Generar una nueva clase.
Nuestro modelo Student se actualizara de la siguiente manera:
class Student < ApplicationRecord
validates :name, presence: true
validates :qualifications, presence: true
composed_of :calculations,
class_name: 'QualificationCalculation',
mapping: [%w(qualifications qualifications)]
La sintaxis de composed_of cuenta con tres opciones, primero el nombre del método al cual haremos referencia (calculations), el nombre de su clase (la clase que crearemos) y el mapeo de la columna qualifications al atributo qualifications en la nueva clase.
Dicho esto procederemos a crear nuestra nueva clase (qualification_calculation.rb) justo en el directorio de modelos.
class QualificationCalculation
attr_accessor :qualifications
def initialize(qualifications)
@qualifications = qualifications
end
def average_calculation
sum_qualifications / qualifications.size
end
private
def sum_qualifications
qualifications.values.inject(0, :+)
end
end
Hecho esto podemos calcular el promedio de calificación de nuestro estudiante de la siguiente manera:
student = Student.first
student.calculations.average_calculation #=> 9
De esta manera nuestro modelo original no cuenta con la responsabilidad de calcular el promedio y además si ocupamos otro calculo lo podemos agregar directamente en nuestra nueva clase QualificationCalculation.
Top comments (0)