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

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, začnu se někdy během debugová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 emaily 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í (yuml.me?)

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”:

A třeba vám pomůže i můj článek s tipy, problémy a řešeními, se kterými jsem se při tvorbě gemu potkal: Vývoj Ruby Gemu — problémy a řešení.

Co si o gemu myslíte? Nechte mi vzkazy tady dole pod článkem. Díky!

Marek Uličný, June 22, 2016