Come posso stampare il contenuto di un oggetto in Rails per un facile debugging?


99

Penso che sto cercando di ottenere l'equivalente PHP di print_r()(print human-readable); attualmente la produzione grezza è:

ActiveRecord::Relation:0x10355d1c0

Cosa dovrei fare?


Nel caso in cui non l'hai visto (dato che hai accettato una risposta pubblicata appena prima della mia), tieni presente che la funzione debug () funziona esattamente come print_r () in PHP.
Andrew

1
Solo per chiunque venga su questa pagina più tardi debug () è obsoleto e non è più incluso come funzione. Non funzionerà. (Ringraziamo stackoverflow.com/users/231309/irongaze-com per averlo indicato più in basso nella pagina.)
0112

Risposte:


210

In genere provo prima .inspect, se questo non mi dà quello che voglio, passerò a .to_yaml.

class User
  attr_accessor :name, :age
end

user = User.new
user.name = "John Smith"
user.age = 30

puts user.inspect
#=> #<User:0x423270c @name="John Smith", @age=30>
puts user.to_yaml
#=> --- !ruby/object:User
#=> age: 30
#=> name: John Smith

Spero che aiuti.


5
Ho scoperto che alcuni output YAML dei record visualizzano più dati (metadati, forse?) Di quanti mi interessa vedere. Se sto cercando la versione YAML di un disco, userò y record_name.attributes. #yè un alias per to_yaml.
Tass

9

definisci il metodo to_s nel tuo modello. Per esempio

class Person < ActiveRecord::Base
  def to_s
    "Name:#{self.name} Age:#{self.age} Weight: #{self.weight}"
  end
end

Quindi quando andrai a stamparlo con #puts mostrerà quella stringa con quelle variabili.


E se non sai quali sono le variabili che contiene?
cjm2671

Può essere più preciso? Stai dicendo, cosa succede se una variabile è un array o un hash? I loro #to_s se ne occuperebbero.
Chris Ledet

Non è formulato correttamente. puts my_model_instancenon chiamerò to_s. Dovrai farlo esplicitamente:puts my_model_instance.to_s
thisismydesign

6

In Rails puoi stampare il risultato nella vista usando il debug 'Helper ActionView :: Helpers :: DebugHelper

#app/view/controllers/post_controller.rb
def index
 @posts = Post.all
end

#app/view/posts/index.html.erb
<%= debug(@posts) %>

#start your server
rails -s

risultati (nel browser)

- !ruby/object:Post
  raw_attributes:
    id: 2
    title: My Second Post
    body: Welcome!  This is another example post
    published_at: '2015-10-19 23:00:43.469520'
    created_at: '2015-10-20 00:00:43.470739'
    updated_at: '2015-10-20 00:00:43.470739'
  attributes: !ruby/object:ActiveRecord::AttributeSet
    attributes: !ruby/object:ActiveRecord::LazyAttributeHash
      types: &5
        id: &2 !ruby/object:ActiveRecord::Type::Integer
          precision: 
          scale: 
          limit: 
          range: !ruby/range
            begin: -2147483648
            end: 2147483648
            excl: true
        title: &3 !ruby/object:ActiveRecord::Type::String
          precision: 
          scale: 
          limit: 
        body: &4 !ruby/object:ActiveRecord::Type::Text
          precision: 
          scale: 
          limit: 
        published_at: !ruby/object:ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
          subtype: &1 !ruby/object:ActiveRecord::Type::DateTime
            precision: 
            scale: 
            limit: 
        created_at: !ruby/object:ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
          subtype: *1
        updated_at: !ruby/object:ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
          subtype: *1

6

Sto usando la gemma awesome_print

Quindi devi solo digitare:

ap @var

2
Non sono un sostenitore dell'installazione di una gemma per qualcosa di così semplice, ma uso regolarmente Awesome Print.
Tass

Questo è davvero buono, quello che alla fine ho fatto nel mio codice è questo: Rails.logger.ap someObject
Aleksandar Pavić

gem install awesome_print (nessuna modifica necessaria a Gemfile)
Jay

4

.inspectè quello che stai cercando, IMO è molto più facile di .to_yaml!

user = User.new
user.name = "will"
user.email = "will@example.com"

user.inspect
#<name: "will", email: "will@example.com">

2

inspectè fantastico ma a volte non abbastanza buono. Ad esempio, BigDecimaldi stampare in questo modo: #<BigDecimal:7ff49f5478b0,'0.1E2',9(18)>.

Per avere il pieno controllo su ciò che viene stampato è possibile ridefinire to_so inspectmetodi. Oppure creane uno tuo per non confondere troppo gli sviluppatori futuri.

  class Something < ApplicationRecord

    def to_s
      attributes.map{ |k, v| { k => v.to_s } }.inject(:merge)
    end

  end

Questo applicherà un metodo (cioè to_s) a tutti gli attributi. Questo esempio eliminerà il brutto BigDecimals.

Puoi anche ridefinire solo una manciata di attributi:

  def to_s
    attributes.merge({ my_attribute: my_attribute.to_s })
  end

Puoi anche creare un mix dei due o in qualche modo aggiungere associazioni.


2

pp fa anche il lavoro, non è richiesta alcuna gemma.

@a = Accrual.first ; pp @a

#<Accrual:0x007ff521e5ba50
 id: 4,
 year: 2018,
 Jan: #<BigDecimal:7ff521e58f08,'0.11E2',9(27)>,
 Feb: #<BigDecimal:7ff521e585d0,'0.88E2',9(27)>,
 Mar: #<BigDecimal:7ff521e58030,'0.0',9(27)>,
 Apr: #<BigDecimal:7ff521e53698,'0.88E2',9(27)>,
 May: #<BigDecimal:7ff521e52fb8,'0.8E1',9(27)>,
 June: #<BigDecimal:7ff521e52900,'0.8E1',9(27)>,
 July: #<BigDecimal:7ff521e51ff0,'0.8E1',9(27)>,
 Aug: #<BigDecimal:7ff521e51bb8,'0.88E2',9(27)>,
 Sep: #<BigDecimal:7ff521e512f8,'0.88E2',9(27)>,
 Oct: #<BigDecimal:7ff521e506c8,'0.0',9(27)>,
 Nov: #<BigDecimal:7ff521e43d38,'0.888E3',9(27)>,
 Dec: #<BigDecimal:7ff521e43478,'0.0',9(27)>,

Puoi anche stampare due istanze di un oggetto:

 pp( Accrual.first , Accrual.second)
`
`
`

-3

Devi usare debug(@var). È esattamente come "print_r".


5
Questa non è una cosa, almeno su Ruby 1.9.x - NoMethodError: metodo undefined `debug 'per main: Object
Irongaze.com
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.