¿Cómo imprimo el contenido de un objeto en Rails para facilitar la depuración?

99

Creo que estoy tratando de obtener el equivalente en PHP de print_r()(imprimir legible por humanos); en la actualidad, la salida sin procesar es:

ActiveRecord::Relation:0x10355d1c0

¿Qué tengo que hacer?

cjm2671
fuente
En caso de que no lo haya visto (ya que aceptó una respuesta publicada justo antes de la mía), tenga en cuenta que la función debug () funciona exactamente como print_r () en PHP.
Andrew
1
Solo para cualquiera que venga a esta página más adelante, debug () está desactualizado y ya no se incluye como función. No funcionará. (Crédito a stackoverflow.com/users/231309/irongaze-com por señalar esto más abajo en la página.)
0112

Respuestas:

210

Por lo general .inspect, lo intento primero , si eso no me da lo que quiero, lo cambio .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 ayude.

Jerhinesmith
fuente
5
Descubrí que algunas salidas YAML de registros muestran más datos (¿metadatos, quizás?) De los que me gustaría ver. Si estoy buscando la versión YAML de un registro, usaré y record_name.attributes. #yes un alias de to_yaml.
Tass
9

defina el método to_s en su modelo. Por ejemplo

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

Luego, cuando vaya a imprimirlo con #puts, mostrará esa cadena con esas variables.

Chris Ledet
fuente
¿Qué pasa si no sabe cuáles son las variables que contiene?
cjm2671
¿Puedes ser mas específico? ¿Estás diciendo qué pasa si una variable es una matriz o un hash? Sus #to_s se encargarían de eso.
Chris Ledet
Esto no está redactado correctamente. puts my_model_instanceno llamaré to_s. Tendrá que hacer eso explícitamente:puts my_model_instance.to_s
thisismydesign
6

En Rails puedes imprimir el resultado en la Vista usando la depuración '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 (en el 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
Papouche Guinslyzinho
fuente
6

Estoy usando la gema awesome_print

Entonces solo tienes que escribir:

ap @var
ljouglar
fuente
2
No soy partidario de instalar una joya para algo tan simple, pero uso Awesome Print con regularidad.
Tass
Esto es realmente bueno, lo que finalmente hice en mi código es esto: Rails.logger.ap someObject
Aleksandar Pavić
gem install awesome_print (no se necesitan ediciones en Gemfile)
Jay
4

.inspectes lo que estás buscando, ¡en mi opinión es mucho más fácil que .to_yaml!

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

user.inspect
#<name: "will", email: "[email protected]">
Kyle Krzeski
fuente
2

inspectes genial, pero a veces no lo suficientemente bueno. Por ejemplo BigDecimalimprime la siguiente manera: #<BigDecimal:7ff49f5478b0,'0.1E2',9(18)>.

Para tener un control total sobre lo que se imprime, puede redefinir to_so inspectmétodos. O cree uno propio para no confundir demasiado a los futuros desarrolladores.

  class Something < ApplicationRecord

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

  end

Esto aplicará un método (es decir to_s) a todos los atributos. Este ejemplo eliminará lo feo BigDecimals.

También puede redefinir solo un puñado de atributos:

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

También puede crear una combinación de los dos o agregar asociaciones de alguna manera .

este es mi diseño
fuente
2

pp también hace el trabajo, no se requiere 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)>,

También puede imprimir dos instancias de un objeto:

 pp( Accrual.first , Accrual.second)
`
`
`
zee
fuente
-3

Necesitas usar debug(@var). Es exactamente como "print_r".

Andrés
fuente
5
Esto no es una cosa, al menos en Ruby 1.9.x - NoMethodError: método indefinido `debug 'para main: Object
Irongaze.com