Ruby Q/A

  1. Имам въпрос, реших че искам да знам в кой клас се намирам и с тази цел докато тествах реших да принтирам класа тоест

    puts self което съответно доведе до грешка

    в последствие установих че

    p self обаче работи

    Въпроса ми е защо?

  2. Друг въпрос който имам е как точно работи array.sort това което разбрах е че използва оператора <=> за сравнение, следователно предполагам че ако си предефинирам този оператор в конкретния за мен клас би трябвало да да мога да направя нещо от сорта на arr.sort!{|x, y| x <=> y}

    направих си тест който обаче хвърля грешка

    class Test
      def initialize(x)
        @x = x
      end
    
      def x
        x
      end
    
      def <=>(other)
        if @x > other.x then return 1 end
        if @x < other.x then return -1 end
        if @x == other.x then return 0 end
      end
    end
    
    t1 = Test.new(5)
    t2 = Test.new(6)
    arr = [Test.new(9) , Test.new(45), Test.new(5), Test.new(8)]
    arr.sort!{|x, y| x <=> y}
    
  3. @Николай, каква грешка ти даде това със селф?

    [11] pry(main)> p self
    main
    => main
    [12] pry(main)> puts self
    main
    => nil
    [13] pry(main)> class Slon
    [13] pry(main)*   p self
    [13] pry(main)*   puts self
    [13] pry(main)* end
    Slon
    Slon
    => nil
    [14] pry(main)> class Slon
    [14] pry(main)*   def initialize
    [14] pry(main)*     p self
    [14] pry(main)*     puts self
    [14] pry(main)*   end
    [14] pry(main)* end
    => nil
    [15] pry(main)> Slon.new
    #<Slon:0x007fefb3a9cef0>
    #<Slon:0x007fefb3a9cef0>
    => #<Slon:0x007fefb3a9cef0>
    

    Форматирай кода на другото - не може да се прочете така. Използвай 3 пъти ` този символ, с нови редове над него.

  4. Работещ пример за Test класа:

    [18] pry(main)> class Test
    [18] pry(main)*   attr_accessor :x
    [18] pry(main)*   def initialize(x)
    [18] pry(main)*     @x = x
    [18] pry(main)*   end
    [18] pry(main)*
    [18] pry(main)*   def <=>(other)
    [18] pry(main)*     @x <=> other.x # numbers already have <=> - just use it
    [18] pry(main)*   end
    [18] pry(main)* end
    => nil
    [19] pry(main)> tests = (1..10).map { |x| Test.new(x) }.shuffle
    => [#<Test:0x007fefb1e2cef0 @x=8>,
     #<Test:0x007fefb1e2cea0 @x=9>,
     #<Test:0x007fefb1e2cf90 @x=4>,
     #<Test:0x007fefb1e2ce78 @x=10>,
     #<Test:0x007fefb1e2cf40 @x=6>,
     #<Test:0x007fefb1e2cf18 @x=7>,
     #<Test:0x007fefb1e2cf68 @x=5>,
     #<Test:0x007fefb1e2cfe0 @x=3>,
     #<Test:0x007fefb1e2d030 @x=2>,
     #<Test:0x007fefb1e2d058 @x=1>]
    [20] pry(main)> tests.sort
    => [#<Test:0x007fefb1e2d058 @x=1>,
     #<Test:0x007fefb1e2d030 @x=2>,
     #<Test:0x007fefb1e2cfe0 @x=3>,
     #<Test:0x007fefb1e2cf90 @x=4>,
     #<Test:0x007fefb1e2cf68 @x=5>,
     #<Test:0x007fefb1e2cf40 @x=6>,
     #<Test:0x007fefb1e2cf18 @x=7>,
     #<Test:0x007fefb1e2cef0 @x=8>,
     #<Test:0x007fefb1e2cea0 @x=9>,
     #<Test:0x007fefb1e2ce78 @x=10>]
    

    Идеята да предефинираш <=> метода е да избегнеш подаването на блок при сортиране на масив от Test инстанции. Без дефиниран <=> метод за Test класа примера би изглеждал така:

    [24] pry(main)> class Test
    [24] pry(main)*   attr_accessor :x
    [24] pry(main)*   def initialize(x)
    [24] pry(main)*     @x = x
    [24] pry(main)*   end
    [24] pry(main)* end
    => nil
    [25] pry(main)> tests = (1..10).map { |x| Test.new(x) }.shuffle
    => [#<Test:0x007fefb3b54910 @x=9>,
     #<Test:0x007fefb3b54870 @x=5>,
     #<Test:0x007fefb3b54848 @x=4>,
     #<Test:0x007fefb3b548c0 @x=7>,
     #<Test:0x007fefb3b547d0 @x=1>,
     #<Test:0x007fefb3b547f8 @x=2>,
     #<Test:0x007fefb3b54938 @x=10>,
     #<Test:0x007fefb3b54898 @x=6>,
     #<Test:0x007fefb3b54820 @x=3>,
     #<Test:0x007fefb3b548e8 @x=8>]
    [26] pry(main)> tests.sort { |first, second| first.x <=> second.x }
    => [#<Test:0x007fefb3b547d0 @x=1>,
     #<Test:0x007fefb3b547f8 @x=2>,
     #<Test:0x007fefb3b54820 @x=3>,
     #<Test:0x007fefb3b54848 @x=4>,
     #<Test:0x007fefb3b54870 @x=5>,
     #<Test:0x007fefb3b54898 @x=6>,
     #<Test:0x007fefb3b548c0 @x=7>,
     #<Test:0x007fefb3b548e8 @x=8>,
     #<Test:0x007fefb3b54910 @x=9>,
     #<Test:0x007fefb3b54938 @x=10>]
    

    Идеята е да енкапсулираш логиката за сравняване на сложни класове вътре в самите класове. Не е нужно тези, които ги иползват да знаят по какъв начин се сравняват. А и ако решиш Test обектите да ги сортираш по друго трябва да го промениш на 1 място, а не на всички, на които ги сортираш. Освен това, винаги можеш да използваш sort с блок и да направиш къстъм сортиране ако ти трябва.

  5. @Николай, дай "Редактирай" на поста си и виж как съм ти го форматирал. Без това форматиране, някои специални символи не се показват в поста ти и това пречи на другите да разберат какво питаш.

    Конкретно за примера ти, той дава следната грешка:

    SystemStackError: stack level too deep
    

    И причината за нея е дефиницията ти на метода Test#x:

    def x
      x
    end
    

    В нея ти реално правиш рекурсия, като x вика x и така безкрай. Вероятно си искал да напишеш това:

    def x
      @x
    end
    

    Освен тази грешка, няма други. Примерът ти работи.

  6. Когато пускам тестовете те файлват което се очаква, но после забелязах че се тества дали Card.new(10, :spades).to_s дава 10 of Spades което като го проверих при мен е така , но rspec връща че теста е файлнал с грешка :

    Failures:
    
      1) Card can be converted to a string
         Failure/Error: expect(Card.new(10, :spades).to_s).to eq '10 of Spades'
         NoMethodError:
           undefined method `expect' for #<RSpec::ExampleGroups::Card:0x268a088>
         # ./test_cards.rb:3:in `block (2 levels) in <top (required)>'
    

    Въпроса ми е дали проблема е в rspec, защото този проблем NoMetgodError ми го връща на всички тестове

    П.С. пробвах ръчно още няколко теста, отново дава че са файлнали докато като ги тествам ръчно връща това което се очаква.

  7. Имам интересн въпрос, така имам клас

    class Child < Parent
    
      attr_accessor :field
    
    end
    

    Child наследява някакви работи и се случва следното ако не съм инициализирал :field обекта от този тип си е Child със всичките му методи и т.н. обаче ако сетна :field на нещо целия обект става от тип символ, защо ?

  8. @Ники, няколко неща:

    1. Дай редакция на поста си и виж как съм ти форматирал кода, за да се чете. Спри да ползваш <code> тагове, не се ползват за форматиране на Markdown. Погледни тук за повече информация.
    2. Направих примера ти по-общ, за да не споделяш код от задачата. Прави така занапред.
    3. И аз, както и Влад, не разбирам обяснението, което даваш. Трябва цялостен пример (но "анонимизиран", без неща от задачата). Или ни изпрати на имейла на курса кода от задачата, с въпрос.

Трябва да сте влезли в системата, за да може да отговаряте на теми.