Active Explorer gem - jednodušší Ruby on Rails debugging

Vít Uličný
·29/04/2024
·6 min.
Máme nový gem!
Nazval jsem ho Active Explorer(https://github.com/rascasone/active_explorer) a dnes bych vám o něm chtěl něco říct — proč je dobrý a tak.
V zásadě funguje jako “awesome_print s vazbami” (v módu pro výpis do konzole) a jako “railroady pro run-time data” (v módu vykreslování grafu).
Jedním příkazem vyexportuje data objektu společně s daty všech objektů, které jsou s ním asociované. Prozkoumává (“explores”) okolí objektu.
Na následujících řádcích vás čeká:
- Co gem dělá
- Proč jsem ho vytvořil
- Jako ho použít
- Plány do budoucna
TL; DR
Pokud nemáte čas číst, tak tady je stručné demo:
1. Tohle přidejte do Gemfile:
gem `active_explorer`
2. Nastavte breakpoint a až program zastaví, zkuste tohle napsat do konzole:
# Console output ex my_object
# Image output (install GraphViz software first) exf my_object
3. A teď se podívejte, co jste udělali ;)
Příklady a podrobný návod najdete na Githubu:https://github.com/rascasone/active_explorer
Co gem dělá?
Gem vypíše všechny atributy objektu a také atributy všech objektů, které s ním jsou propojené vazbami `has_many` nebo `belongs_to`.
Výstupem je:
- text do konzole (podobný výstupu z awesome_print),
- obrázek uložený do souboru (podobně jako v railroady).
Celé to funguje pouze nad modely — tj. nad instancemi Active Record.
Proč jsem ho vytvořil?
Stává se mi, že jakmile projekt naroste do určité velikosti, tak se začnu během debuggování ztrácet. Prohlížím mnoho objektů a jejich atributy, dívám se, na jaké další objekty jsou napojeny, zastavuji na mnoha breakpointech. A často potřebuji rychle prozkoumat aktuální data — podívat se na atributy objektu a jeho vazby na další objekty.
Uvedu příklad. Na současném projektu pracujeme s třídami, které popisují zákazníka a jeho interakci s e-maily a webovými formuláři.
# Customer is someone either addressed by email or a visitor on a web page class Customer < ActiveRecord::Base has_many :greetings has_many :requests end
# Greeting email is received by Customer and might lead to Request class Greeting < ActiveRecord::Base belongs_to :customer has_many :requests, through: greeting_to_request end
# Association Model that connects Greeting and Request class GreetingToRequest < ActiveRecord::Base belongs_to :greeting belongs_to :request end
# Request is created by Customer (either directly through web page or based on Greeting email) class Request < ActiveRecord::Base belongs_to :customer has_many :greetings, through: greeting_to_request has_many :offers end
# Offer is created in response to Request and consists of several Calculations class Offer < ActiveRecord::Base belongs_to :request has_many :calculations end
# Calculation is a part of Offer class Calculation < ActiveRecord::Base belongs_to :offer has_many :orders end
# Order is created by Customer based on Calculation class Order < ActiveRecord::Base belongs_to :offer has_many :calculations end
Už v tomto malém příkladu se objevuje mnoho vazeb a ty jdou hlouběji a hlouběji.
Několikrát jsem debuggoval metodu, která vytváří Kalkulace a v tu chvíli mě zajímalo z jakých objektů Kalkulace vychází.
Obecně jsem často řešil následující:
- z jakých Požadavků vychází,
- zda Požadavek vychází z Oslovení,
- s jakým Zákazníkem ja spojena,
- jaké Objednávky z ní vzešly.
Musel jsem tím pádem volat následující:
calculation.offer.request calculation.offer.request.customer calculation.offer.request.greetings calculation.orders
Mnoho psaní.
Jasně, některé atributy jako třeba `customer` lze delegovat. Taky konzole umožňuje elegantně opakovat poslední příkazy a (většinou) doplňovat názvy parametrů a metod. Ale občas se to prostě naskládá a tak jsem si říkal, že by to chtělo všechno udělat jedním jediným příkazem a přehledně vše vypsat.
A tady ten příkaz je:
ex calculation
Super ;)
Neříkám, že ten příkaz používám každý den a tak často jako `ap` z Awesome Printu, ale občas je dobré mít ho po ruce. Čas od času ho použiju, abych "prozkoumal okolí" a zjistil "kde jsem".
Mód, který generuje graf je zase dobrý, když potřebuju něco probrat s kolegy a chceme mít jasno v tom, o čem mluvíme.
Jak ho používat?
Prvně, funguje pouze s objekty typu Active Record.
Gem lze používat dvěma způsoby:
- výstup do konzole,
- výstup jako obrázek do souboru (s využitím knihovny GraphViz).
Výstup do konzole
Příkazem, který zadáte buď v kódu nebo při debuggu napíšete do IRB (podobně jako `ap` od Avesome Printu):
ex <your_object>
Příklad výstupu:
ex calculation
# => Console output:
Calculation(1232) {:offer_id=>554142781, :company_id=>7} -> belongs to Offer(554142781) {:request_id=>980190974, :created_at=>Wed, 22 Jun 2016 14:36:57 CEST +02:00} -> belongs to Request(980190974) {:car_cylinder_capacity=>1500, :car_performance=>160} -> belongs to Customer(980190974) {:name=>"Marry", :surname=>"Helpful"} -> belongs to ZipCode(7828) {:zip_code=>"51101", :city_id=>97942}
Výstup jako obrázek
Druhou možností je vygenerovat graf propojených objektů s použitím GraphViz software (tady je návod k instalaci).
Příkaz:
exf <your_object>
Příklad výstupu:
Soubor se uloží do kořenového adresáře.
Plány
Komunita
Rád bych rozšířil gem mezi Ruby komunitu, aby mohl být pořádně otestován, a aby se objevily nové nápady pro jeho využití a rozšíření. Pokud se vám gem líbí, nebo naopak nelíbí dejte mi vědět — v diskuzi dole.
Chytání bugů
Vím o drobných nedostatcích, takže nějaké to testování a vývoj bude potřeba.
Rozšíření
Chci udělat výstup hezčí a použitelnější:
- použít barvy,
- vytvořit interaktivní graf místo statického obrázku,
- exportovat do SVG,
- exportovat graf do online služby pro lepří možnost sdílení.
Rady pro vytváření gemu
Pokud zvažujete vytvoření gemu — udělejte ho. Dokončit a vyladit nějakou knihovnu vám pomůže stát se lepším programátorem. A taky pomůžete ostatním = karma!!! ;)
Krátký seznam tutoriálů o tom “Jak vytvořit gem”:
Máte nápad na nový projekt?
Popište nám ho! Rádi odpovíme na všechny vaše dotazy, nebo rovnou domluvíme termín schůzky.
Ozvěte se Vítovi! Vše s vámi projedná a probere.
Vít Uličný
Zakladatel & CEO
