ฉันจะพิมพ์เนื้อหาของออบเจ็กต์ใน Rails ได้อย่างไรเพื่อให้ง่ายต่อการดีบั๊ก


101

ฉันคิดว่าฉันกำลังพยายามทำให้ PHP เทียบเท่าprint_r()(พิมพ์ที่มนุษย์อ่านได้); ในปัจจุบันผลลัพธ์ดิบคือ:

ActiveRecord::Relation:0x10355d1c0

ฉันควรทำอย่างไรดี?


ในกรณีที่คุณไม่ได้เห็นมัน (เนื่องจากคุณได้รับการยอมรับคำตอบโพสต์ก่อนเหมือง) ทำบันทึกว่าการแก้ปัญหา () ฟังก์ชันการทำงานตรงเช่น print_r () ใน PHP
Andrew

1
สำหรับใครก็ตามที่เข้ามาในหน้านี้ในภายหลังใน debug () จะล้าสมัยและไม่รวมเป็นฟังก์ชันอีกต่อไป จะไม่ทำงาน (ให้เครดิตstackoverflow.com/users/231309/irongaze-comเพื่อชี้ประเด็นต่อไปในหน้า)
0112

คำตอบ:


213

โดยทั่วไปแล้วฉันจะลองก่อน.inspectถ้าสิ่งนั้นไม่ได้สิ่งที่ฉันต้องการฉันจะเปลี่ยนไป.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

หวังว่าจะช่วยได้


6
ฉันพบว่าผลลัพธ์ของบันทึก YAML บางรายการแสดงข้อมูลมากกว่า (ข้อมูลเมตาอาจจะ?) มากกว่าที่ฉันอยากเห็น ถ้าฉันกำลังมองหารุ่น YAML y record_name.attributesของการบันทึกฉันจะใช้ เป็นนามแฝงสำหรับ#y to_yaml
Tass

9

กำหนดวิธีการ to_s ในโมเดลของคุณ ตัวอย่างเช่น

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

จากนั้นเมื่อคุณพิมพ์ด้วย #put มันจะแสดงสตริงนั้นพร้อมกับตัวแปรเหล่านั้น


จะเกิดอะไรขึ้นถ้าคุณไม่รู้ว่าตัวแปรนั้นมีอะไรบ้าง?
cjm2671

คุณสามารถเจาะจงมากขึ้นได้หรือไม่? คุณกำลังพูดว่าถ้าตัวแปรเป็นอาร์เรย์หรือแฮชล่ะ? #to_s ของพวกเขาจะดูแลสิ่งนั้น
Chris Ledet

วลีนี้ไม่ถูกต้อง puts my_model_instanceจะไม่โทรto_s. คุณจะต้องทำอย่างชัดเจน:puts my_model_instance.to_s
thisismydesign

6

ใน Rails คุณสามารถพิมพ์ผลลัพธ์ใน View โดยใช้ 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

ผลลัพธ์ (ในเบราว์เซอร์)

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

ฉันใช้อัญมณี awesome_print

ดังนั้นคุณต้องพิมพ์:

ap @var

2
ฉันไม่ใช่ผู้สนับสนุนการติดตั้งอัญมณีสำหรับสิ่งที่เรียบง่าย แต่ฉันใช้ Awesome Print เป็นประจำ
Tass

นี่เป็นสิ่งที่ดีจริงๆในที่สุดสิ่งที่ฉันทำในรหัสของฉันคือ: Rails.logger.ap someObject
Aleksandar Pavić

gem install awesome_print (ไม่จำเป็นต้องแก้ไข Gemfile)
Jay


3

pp ก็ทำงานได้เช่นกันไม่จำเป็นต้องมีอัญมณีใด ๆ

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

คุณยังสามารถพิมพ์ออบเจ็กต์ได้สองอินสแตนซ์:

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

2

inspectดีมาก แต่บางครั้งก็ไม่ดีพอ เช่นBigDecimalพิมพ์แบบนี้:#<BigDecimal:7ff49f5478b0,'0.1E2',9(18)> .

เพื่อให้สามารถควบคุมสิ่งที่พิมพ์ได้ทั้งหมดคุณสามารถกำหนดto_sหรือinspectวิธีการใหม่ได้ หรือสร้างของคุณเองเพื่อไม่ให้เกิดความสับสนกับผู้พัฒนาในอนาคตมากเกินไป

  class Something < ApplicationRecord

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

  end

สิ่งนี้จะใช้วิธีการ (เช่นto_s) กับแอตทริบิวต์ทั้งหมด ตัวอย่างนี้จะกำจัดสิ่งที่น่าเกลียดBigDecimalsตัวอย่างนี้จะได้รับการกำจัดของน่าเกลียด

นอกจากนี้คุณยังกำหนดแอตทริบิวต์ได้เพียงไม่กี่รายการเท่านั้น:

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

นอกจากนี้คุณยังสามารถสร้างผสมของทั้งสองหรืออย่างใดเพิ่มความสัมพันธ์


-3

debug(@var)คุณจำเป็นต้องใช้ มันเหมือนกับ "print_r" ทุกประการ


5
นี่ไม่ใช่เรื่องอย่างน้อยใน Ruby 1.9.x - NoMethodError: วิธีการที่ไม่ได้กำหนด `` debug 'สำหรับ main: Object
Irongaze.com
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.