Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
March 7, 2020 06:24 pm GMT

Getting Cozy with Ruby

When I first approached Ruby, I basically looked at it like "dynamic C++", because that was the best analogue I had. Of course, that has required some tweaking. This post talks about some Ruby-specific idioms that aren't directly related to concepts I knew, and assumes you already use another class-based OOP language such as C++, Java, or Python.

Now that I've been using Ruby for about three days, I'm obviously a complete expert and to be implicitly trusted (heh). If you do see something wrong, please correct me!

Huge thanks to @dvik1950 on the Ruby exercism mentored track for many of these.

I know this splash image only mildly applies but it was too cool not to use. You can't change my mind.

Testing

This is a dynamic language. I am so very much a static kinda person, so unit testing is pretty much the first priority for not losing hair/sleep.

I found the easiest to start with is minitest:

$ gem install minitest

Then, in my_math_test.rb:

require 'minitest/autorun'require_relative 'my_math'# MyMath sanity testsclass MyMathTest < Minitest::Test  def test_times_two    # skip    assert_equal 8, MyMath.my_times_two(4)  endend

Uncomment skip to skip the test, which avoids commenting/uncommenting the whole function. Also, the MyMathTest < Minitest::Test syntax is how you define a subclass, so MyMathTest inherits from Minitest::Test.

For a much more involved solution, there's rspec which provides a testing DSL instead of using Ruby functions. Here's what that test might look like:

describe MyMath do   it "multiplies 4 by 2" do     math = MyMath.new     expect(math.my_times_two(4)).to eq(8)  endend

This reminds me of using Mocha with Chai in JavaScript. There's an intro guide here.

%w

Don't do this:

JOES = ["average", "DiMaggio", "morning"]

Do this:

JOES = %w[average DiMaggio morning]

Whoa! Also, %i works for symbols:

SYMS = %i[one two three]# [:one, :two, :three]

freeze

Not planning to ever change your JOES constant? Tell Ruby that you mean it and freeze 'em:

JOES = %w[average DiMaggio morning].freeze

Now it's actually immutable! Read a lot more about Ruby constants here.

String interpolation

Basically, it does it. This works:

def say_name(name)  output = "Hello, "  output << name  output << "!"  puts outputend

This is better:

def say_name(name)  puts "Hello, " + name + "!"end

But you probably want this:

def say_name(name)  puts "Hello, #{name}!"end

class << self

To redefine a method on self, so you can call MyClass.my_method, you can define it on self explicitly:

class MyClass  def self.my_method(str)    puts str  endend

If you're doing this a bunch, you can open up the eigenclass, or singleton class, directly:

class MyClass  class << self    def my_method(str)      puts str    end  endend

I think that's a little less noisy, even at the cost of some extra lines and indentation. If you want to go super concise, you can just dot-operator your way all the way in:

class MyClassenddef MyClass.my_method(str)  puts strend

This class << self is also the best way to make a private method:

class MyClass  class << self    private    def my_private_method(str)      puts str    end  endend

Otherwise, you have to use private_class_method which I think looks gross:

class MyClass  private_class_method def self.my_private_method(str)    puts str  endend

attr_accessor

You can publicly expose instance variables directly:

class MyClass  def initialize    @value = 0  end  def show_value    puts @value  endend

You define the constructor with initialize().

In Ruby, however, it's extremely easy to create getters and setters and usually preferable. You can manually do so:

class MyClass  def initialize    @value = 0  end  def value    @value  end  def value=(new_value)    @value = new_value  end  def show_value    puts value # don't point to the `@value` var, send the `value` message  endend

It's usually better to create both at once with attr_accessor:

class MyClass  attr_accessor :value  def initialize    @value = 0  end  def show_value    puts value  endend

You can also use attr_reader or attr_writer for just the getter or just the setter, respectively.

The benefit is that now if this logic needs to change, all you need to do is define that method, and every call site automatically reflects the new logic.

Structs

You don't have to use nested arrays and whatnot for complex data just because we're using a dynamic language. Ruby provides a Struct class for structured data, which gives you these accessors methods automatically

This is a contrived example, but instead of this:

class MyRect  attr_reader :rect_dims  def initialize(arr)    @rect_dims = arr  end  def show_size    puts "Size: #{rect_dims[0]}x#{rect_dims[1]}"  endend

Do this:

class MyRect  attr_reader :rect_dims  def initialize(arr)    @rect_dims = make_dim_struct(arr)  end  def show_size    puts "Size: #{rect_dims.width}x#{rec_dims.height}"  end  RectDims = Struct.new(:width, :height)  def make_dim_struct(arr)    arr.collect { |dims| RectDims.new(dims[0], dims[1]) }  endend

As before, the whole point is to localize the definition of your data's structure to one single place, should it need to change again.

rubocop

Rubocop is a linter that adheres to the Ruby Style Guide. Do this:

$ gem install rubocop

Then always do this:

$ rubocop myFile.rb

Fix everything it says to fix, and if you don't understand what it's saying or why, look it up. Learning!

Here's a repl.it with the code from this post:

To be continued...

There's actually a bunch of cool stuff out there. Methods like gsub and inject stand out as some pleasant surprises from my first explorations. This comment from @ben has been spot on:

Ruby is a scripting language at its core. One command after another. Almost brutally simplistic.

Id recommend opening up IRB and typing some commands. Its actually pretty close to coding in the environment.

Ruby is sort of object oriented, sort of functional, and has a few ways to do the same thing most of the time. Its a bit of a free-for-all.

There really is a bit of everything here. It's got a bit of pretty much every language I've previously used! Nailing down the clearest solution or most correctly applied pattern is a little tricker.

I looked at Ruby a long time ago, as one of my very first forays into programming. I liked how concise it was, and why's poignant guide is a really fun read - if you haven't read it, you should at least give it a try even if you're not necessarily targetting Ruby just for how unique it is.

However, I'm having a lot more fun with the language returning again as a more experienced coder. I think having the context I've built using a variety of different types of languages has helped me understand how to apply Ruby effectively. It was difficult for me to learn how to use Ruby at the same time as learning how to program in a general sense, despite how easy it is to get up and running.

I don't know that I'd personally recommend Ruby as a first programming language. There are so many paradigms available with so little friction. Do you agree or disagree?

Photo by Road Trip with Raj on Unsplash


Original Link: https://dev.to/deciduously/getting-cozy-with-ruby-1l6f

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To