DEV Community

Vicki Langer
Vicki Langer

Posted on

Picking up Ruby, as a Python Dev & a mini fish app

This is a continuation of Picking up Ruby Fast, as a Python Dev. Again, expect examples with no math and minimal crappy names


Sending Messages to Multiple Methods?

I'm not sure if this is a thing you can do in Python, but you can do it in Ruby. In the example below feed "dogs" if meal_time?(5) runs 2 methods at once.

This ? in mealt_time? is also new to me and I have not seen it in Python. In Python, I would've done my variable like is_it_meal_time.

#ruby
def meal_time? time_hrs
  if time_hrs >=5
    puts "cat is singing song of his people, guess it's food time"
    true
  else
    puts "tell cat to try again in an hour"
    false
  end
end

def feed pet
    puts "put food in #{pet} bowl\n"

end

feed "cats" if meal_time?(4)
feed "dogs" if meal_time?(5)
feed "cats" if meal_time?(18)
feed "dogs" if meal_time?(18)
Enter fullscreen mode Exit fullscreen mode

Classes

Classes look a little different from Python to Ruby, but looks like it's basically the same concept. The attr_accessor and @ are new parts to me.

Mini Fish App combining the stuff I've reviewed so far

I've been meaning to build a mini app for tracking the levels of things in my fish tank, so here it is.

# ruby
class Water_Level
  attr_accessor :time, :ph, :ammonia, :nitrites, :nitrates, :temp

  def initialize(ph, ammonia, nitrites, nitrates, temp)
    @time = Time.now
    @ph = ph
    @ammonia = ammonia
    @nitrites = nitrites
    @nitrates = nitrates
    @temp = temp
  end
end

Water_Level.new.time

class Levelizer
  def initialize(title)
    @title  = title
    @levels = [] 
  end

  def add_a_level(ph, ammonia, nitrites, nitrates, temp)
    # The << means add to the end of the array
    @levels << Level.new(ph, ammonia, nitrites, nitrates, temp)
  end

  def show_timeline
    puts "Fishify: #{@title} has tracked #{@levels.count} Levels"

    @levels.sort_by { |t|
      t.time
    }.reverse.each { |t|
      puts "#{t.ph} #{t.ammonia} #{t.nitrites} #{t.nitrates} #{t.temp} #{t.time}"
    }
  end
end

myapp = Levelizer.new "Vicki's Betta Tank"

myapp.add_a_level 7.4, 0, 0, 0, 78.2
myapp.add_a_level 7.4, 0, 0, 0, 72.3
myapp.add_a_level 7.2, 0, 0, 0, 79.1

myapp.show_timeline

"""
# output
Fishify: Vicki's Betta Tank has tracked 3 Levels
7.2 0 0 0 79.1 Thu Nov 19 2020 14:04:59 GMT-0500 (Eastern Standard Time)
7.4 0 0 0 72.3 Thu Nov 19 2020 14:04:59 GMT-0500 (Eastern Standard Time)
7.4 0 0 0 78.2 Thu Nov 19 2020 14:04:59 GMT-0500 (Eastern Standard Time)
"""

Enter fullscreen mode Exit fullscreen mode

Reminder to self: do not work at places that think unpaid work is acceptable.


If you missed the first post in this series, I've heard it's a good read and there's cats.

Top comments (2)

Collapse
 
topofocus profile image
Hartmut B.

You can easily rewrite

  def show_timeline
    puts "Fishify: #{@title} has tracked #{@levels.count} Levels"

    @levels.sort_by( &:time ) 
                 .reverse
                 .each { |t|  puts "#{t.ph} #{t.ammonia} #{t.nitrites} #{t.nitrates} #{t.temp{t.time}"    }
  end
end
Enter fullscreen mode Exit fullscreen mode

Next: the output in the iteration is not recommended.
map and join are your friends.

  def show_timeline
    puts "Fishify: #{@title} has tracked #{@levels.count} Levels"
    puts @levels.sort_by( &:time ) 
                         .reverse
                         .map{ |t| [t.ph, t.ammonia, t.nitrites, t.nitrates, t.time].join(" ")}
                         .join "\n"
 end
Enter fullscreen mode Exit fullscreen mode

Then the code is quite different from any python program, I guess. To me its more readable. Don't now, how this feels from your perspective,

Collapse
 
vickilanger profile image
Vicki Langer

Oh yeah! I was already told I should probably use .map most times that I see .each. Forgot about that.

adds to notes "no output in an iteration"

I can see how this works better. Thanks!