Como faço para imprimir o conteúdo de um objeto no Rails para facilitar a depuração?


99

Acho que estou tentando obter o equivalente em PHP de print_r()(print human-readable); no momento, a saída bruta é:

ActiveRecord::Relation:0x10355d1c0

O que devo fazer?


Caso você não tenha visto (já que aceitou uma resposta postada pouco antes da minha), observe que a função debug () funciona exatamente como print_r () em PHP.
Andrew

1
Apenas para qualquer um que venha a esta página posteriormente em debug () está desatualizado e não é mais incluído como uma função. Não vai funcionar. (Crédito para stackoverflow.com/users/231309/irongaze-com por apontar isso mais adiante na página.)
0112

Respostas:


210

Geralmente tento primeiro .inspect, se isso não me der o que quero, mudo para .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

Espero que ajude.


5
Descobri que algumas saídas YAML de registros exibem mais dados (metadados, talvez?) Do que gostaria de ver. Se estou procurando a versão YAML de um registro, usarei y record_name.attributes. #yé um alias para to_yaml.
Tass

9

defina o método to_s em seu modelo. Por exemplo

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

Então, quando você for imprimi-lo com #puts, ele exibirá aquela string com essas variáveis.


E se você não souber quais são as variáveis ​​que ele contém?
cjm2671

Você pode ser mais específico? Você está dizendo, e se uma variável for um array ou hash? Seus #to_s cuidariam disso.
Chris Ledet

Isso não está formulado corretamente. puts my_model_instancenão vai ligar to_s. Você terá que fazer isso explicitamente:puts my_model_instance.to_s
thisismydesign

6

No Rails você pode imprimir o resultado na View usando o 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

resultados (no navegador)

- !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

Estou usando a gema awesome_print

Então você só precisa digitar:

ap @var

2
Não sou um defensor da instalação de uma gema para algo tão simples, mas eu uso o Awesome Print regularmente.
Tass

Isso é muito bom, o que eu finalmente fiz no meu código foi o seguinte: Rails.logger.ap someObject
Aleksandar Pavić

gem install awesome_print (nenhuma edição necessária para Gemfile)
Jay

4

.inspecté o que você está procurando, é muito mais fácil do que IMO .to_yaml!

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

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

2

inspecté ótimo, mas às vezes não é bom o suficiente. Por exemplo, BigDecimalimprime assim: #<BigDecimal:7ff49f5478b0,'0.1E2',9(18)>.

Para ter controle total sobre o que é impresso, você pode redefinir to_sou inspectmétodos. Ou crie o seu próprio para não confundir demais os desenvolvedores futuros.

  class Something < ApplicationRecord

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

  end

Isso aplicará um método (isto é to_s) a todos os atributos. Este exemplo vai acabar com o feio BigDecimals.

Você também pode redefinir apenas alguns atributos:

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

Você também pode criar uma combinação dos dois ou, de alguma forma, adicionar associações.


2

pp também faz o trabalho, não é necessário exigir nenhuma gema.

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

Você também pode imprimir duas instâncias de um objeto:

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

-3

Você precisa usar debug(@var). É exatamente como "print_r".


5
Isso não é uma coisa, pelo menos no Ruby 1.9.x - NoMethodError: método indefinido `debug 'para main: Object
Irongaze.com
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.