Jak wydrukować zawartość obiektu w Railsach, aby ułatwić debugowanie?

100

Myślę, że próbuję uzyskać odpowiednik PHP print_r()(drukuj czytelny dla człowieka); obecnie surowa produkcja to:

ActiveRecord::Relation:0x10355d1c0

Co powinienem zrobić?

cjm2671
źródło
Jeśli go nie widziałeś (ponieważ zaakceptowałeś odpowiedź wysłaną tuż przed moją), zwróć uwagę, że funkcja debug () działa dokładnie tak samo, jak print_r () w PHP.
Andrew
1
Tylko dla każdego, kto odwiedza tę stronę później w funkcji debug (), jest przestarzały i nie jest już uwzględniany jako funkcja. Nie zadziała. ( Podziękowania dla stackoverflow.com/users/231309/irongaze-com za wskazanie tego w dalszej części strony)
0112

Odpowiedzi:

211

Generalnie najpierw próbuję .inspect, jeśli to nie daje mi tego, czego chcę, przełączam się na .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

Mam nadzieję, że to pomoże.

jerhinesmith
źródło
6
Zauważyłem, że niektóre wyjścia rekordów YAML wyświetlają więcej danych (być może metadanych?), Niż chciałbym zobaczyć. Jeśli szukam wersji YAML rekordu, którego użyję y record_name.attributes. #yjest aliasem dla to_yaml.
Tass
9

zdefiniuj metodę to_s w swoim modelu. Na przykład

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

Następnie, gdy przejdziesz do wydrukowania go z #puts, wyświetli ten ciąg z tymi zmiennymi.

Chris Ledet
źródło
A jeśli nie wiesz, jakie zawiera zmienne?
cjm2671
Czy mógłbyś to sprecyzować? Mówisz, co jeśli zmienna jest tablicą lub hashem? Ich #to_s by się tym zajęło.
Chris Ledet
To nie jest poprawnie sformułowane. puts my_model_instancenie zadzwoni to_s. Będziesz musiał to wyraźnie zrobić:puts my_model_instance.to_s
thisismydesign
6

W Railsach można wydrukować wynik w widoku przy użyciu polecenia debugowania '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

wyniki (w przeglądarce)

- !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
Papouche Guinslyzinho
źródło
6

Używam awesome_print gem

Więc wystarczy wpisać:

ap @var
ljouglar
źródło
2
Nie jestem zwolennikiem instalowania klejnotu za coś tak prostego, ale regularnie używam Awesome Print.
Tass
To jest naprawdę dobre, to, co ostatecznie zrobiłem w swoim kodzie, to: Rails.logger.ap someObject
Aleksandar Pavić
gem zainstaluj awesome_print (bez zmian w Gemfile)
Jay
4

.inspectjest tym, czego szukasz, jest o wiele łatwiejsze niż IMO .to_yaml!

user = User.new
user.name = "will"
user.email = "[email protected]"

user.inspect
#<name: "will", email: "[email protected]">
Kyle Krzeski
źródło
2

inspectjest świetny, ale czasami nie jest wystarczająco dobry. Np BigDecimaldrukuje tak: #<BigDecimal:7ff49f5478b0,'0.1E2',9(18)>.

Aby mieć pełną kontrolę nad tym, co jest drukowane, możesz zmienić definicję to_slub inspectmetody. Lub stwórz własny, aby nie zmylić zbytnio przyszłych programistów.

  class Something < ApplicationRecord

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

  end

Spowoduje to zastosowanie metody (tj. to_s) Do wszystkich atrybutów. Ten przykład pozbędzie się brzydoty BigDecimals.

Możesz także przedefiniować tylko kilka atrybutów:

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

Możesz także stworzyć połączenie tych dwóch lub w jakiś sposób dodać skojarzenia.

to mój projekt
źródło
2

pp też wykonuje swoją pracę, nie jest wymagany żaden klejnot.

@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)>,

Możesz również wydrukować dwa wystąpienia obiektu:

 pp( Accrual.first , Accrual.second)
`
`
`
zee
źródło
-3

Musisz użyć debug(@var). Dokładnie tak, jak „print_r”.

Andrzej
źródło
5
To nie jest rzecz, przynajmniej na Ruby 1.9.x - NoMethodError: undefined method `debug 'for main: Object
Irongaze.com