Last active
November 14, 2019 19:16
-
-
Save quarkgluant/76b9fa9d2df62fa23f94a89b3a666331 to your computer and use it in GitHub Desktop.
Pistes de réflexion sur le kata ActiveRecord like
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ClassMethods | |
# ce module sera "inclus" avec extend, donc | |
# toutes les méthodes de ce module seront des méthodes de classe | |
# les 2 méthodes ci-dessous, ressemblent à attr_accessor mais "de classe". | |
# l'idée est d'utiliser non pas des variables de classe (@@ids) mais des | |
# variables d'instances de classe (à ne pas confondre avec les variables d'instance) | |
# puisque une classe est aussi un objet en Ruby | |
def ids | |
@ids ||= 0 | |
end | |
def ids=(number) | |
@ids = number | |
end | |
def new_id | |
self.ids = (ids + 1) | |
end | |
# la méthode all, au lieu d'utiliser une variable de classe telle @@all, dans | |
# laquelle on mettrai chaque nouvel instance de Car lors de l'instantiation dans la | |
# méthode initialize de Car, utilise ObjectSpace#each_object | |
def all | |
ObjectSpace.each_object(self).to_a | |
end | |
def find(id:) | |
all.select { |instance| instance.id == id }&.first | |
end | |
# cette méthode génère dynamiquement les méthodes find_by_TRUC | |
def make_attr_finders | |
new.public_methods(false).each do |meth| | |
next if meth.to_s.end_with? '=' | |
define_singleton_method "find_by_#{meth}" do |arg| | |
all.select { |instance| instance.send(meth) == arg } | |
end | |
end | |
end | |
# ce hook de Ruby n'est pas utilisé ici, juste pour info | |
def self.extended(base) | |
puts "#{self} (ClassMethods) a été inclus/étendu dans #{base}" | |
end | |
end | |
module InstanceMethods | |
# ce module étant ensuite inclus avec "include", toutes ses méthodes seront des méthodes d'instance | |
def initialize | |
klass = self.class | |
self.id = klass.send :new_id | |
end | |
# but esthétique, pas utile pour le fonctionnement du kata | |
def to_s | |
"#{self.class} #{id}" | |
end | |
# ce hook de Ruby n'est pas utilisé ici, juste pour info | |
def self.included(base) | |
puts "#{self} (ClassMethods) a été inclus/étendu dans #{base}" | |
end | |
end | |
class Car | |
extend ClassMethods | |
include InstanceMethods | |
attr_accessor :id, :color, :nb_portes | |
def motor | |
%w[diesel gazoline electric].sample | |
end | |
end | |
first_car = Car.new | |
second_car = Car.new | |
third_car = Car.new | |
puts "first_car.id: #{first_car.id}" #=> 1 | |
puts "third_car.id: #{third_car.id}" #=> 3 | |
puts "Car.all: #{Car.all}" #=> [#<Car:0x00000000013f3210 @id=1>, #<Car:0x00000000013f37b0 @id=3>, #<Car:0x00000000013f38a0 @id=2>] | |
puts "Car.find(id: 3): #{Car.find(id: 3)}" #=> Car 3 | |
Car.make_attr_finders | |
puts "Car.find_by_motor('electric'): #{Car.find_by_motor('electric')}" | |
puts "Car.find_by_id(3): #{Car.find_by_id(3)}" #=>[#<Car:0x000000000200ab70 @id=3>] | |
puts first_car.methods(false) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ceci n'est PAS LA solution, ni même UNE solution, juste quelques pistes de réflexion qui ne demandent qu'à être améliorées ou radicalement modifiées. Par exemple, on est obligé d'avoir (ligne 85)
Car.make_attr_finders
, ce qui n'est pas beau