Skip to content

Latest commit

 

History

History
201 lines (147 loc) · 4.42 KB

File metadata and controls

201 lines (147 loc) · 4.42 KB

Lessons learned using Ruby

Method lookup

ruby-method-lookup

Complex regular expressions

Use regex literals with the x option:

%r{
    <regex_part_1> # you can add comments
    <regex_part_2> # and end of lines
}x

Exceptions

  • rescue without a class will capture StandardError and its children.

    • It won't capture Ruby internal errors, which is fine most of the time.
  • raise with no current exception in $! will raise a RuntimeError (which is a child of StandardError).

Docs: https://docs.ruby-lang.org/en/master/Exception.html

Memoization in accessors

  • Use memoization in accessors when needed.

    def some_attribute
      @some_attribute ||= some_network_call
    end

    To avoid calling the network again if the first time it returned nil or false:

    def some_attribute
      return @some_attribute if defined? @some_attribute
      @some_attribute = some_network_call
    end
  • To avoid making your code unreadable, use gems that do memoization for you.

Docs: https://www.justinweiss.com/articles/4-simple-memoization-patterns-in-ruby-and-one-gem/

&:symbol - Symbol to Proc / &Proc - Proc to Block / Block to Proc

Look at these specs:
RSpec.configure do |config|
config.default_formatter = "doc"
end
RSpec.describe "'&' operator in the context of procs" do
context "when applied to a symbol" do
it "sends 'to_proc' to the symbol" do
def some_method(&block)
expect(block).to match a_kind_of Proc
end
some_method(&:each)
end
end
context "when applied to a method's argument" do
it "converts the block given to a Proc" do
def some_method(&block)
expect(block).to match a_kind_of Proc
end
some_method do
# nothing
end
end
end
context "when applied to a Proc" do
it "converts the Proc into a block" do
def some_method
yield
end
some_method(&lambda {})
end
end
end

dup vs. clone

Look at these specs:
RSpec.configure do |config|
config.default_formatter = "doc"
config.alias_example_to :they
end
RSpec.describe "dup vs. clone" do
they "both create shallow copies" do
arr = %w[an array of strings]
dup_arr = arr.dup
clone_arr = arr.clone
expect(dup_arr.object_id).not_to eq arr.object_id
expect(clone_arr.object_id).not_to eq arr.object_id
arr_object_ids = arr.map(&:object_id)
# the objects inside the array are not copied, only their references.
expect(dup_arr.map(&:object_id)).to contain_exactly(*arr_object_ids)
expect(clone_arr.map(&:object_id)).to contain_exactly(*arr_object_ids)
end
describe "dup" do
context "copies without special attributes" do
it "ignores freezed status" do
str = "some constant string".freeze
dup_str = str.dup
expect(str).to be_frozen
expect(dup_str).not_to be_frozen
end
it "ignores tainted status" do
skip "can't find a way to create a tainted object"
# Objects created from external sources are marked as tainted.
# Any object derived from this object is marked as tainted.
obj = ENV["GEM_HOME"]
dup_obj = obj.dup
expect(obj).to be_tainted
expect(dup_obj).not_to be_tainted
end
it "ignores singleton class" do
obj = %w[some kind of object]
def obj.method_in_singleton_class
# this method goes to obj's singleton class.
end
dup_obj = obj.dup
expect(obj).to respond_to(:method_in_singleton_class)
expect(dup_obj).not_to respond_to(:method_in_singleton_class)
end
end
end
describe "clone" do
context "copies the object as it is (including special attributes)" do
it "copies freezed status" do
str = "some constant string".freeze
clone_str = str.clone
expect(str).to be_frozen
expect(clone_str).to be_frozen
end
it "copies tainted status" do
skip "can't find a way to create a tainted object"
# Objects created from external sources are marked as tainted.
# Any object derived from this object is marked as tainted.
obj = ENV["GEM_HOME"]
clone_obj = obj.clone
expect(obj).to be_tainted
expect(clone_obj).not_to be_tainted
end
it "copies singleton class" do
obj = %w[some kind of object]
def obj.method_in_singleton_class
# this method goes to obj's singleton class.
end
clone_obj = obj.clone
expect(obj).to respond_to(:method_in_singleton_class)
expect(clone_obj).to respond_to(:method_in_singleton_class)
end
end
end
end

Enumerator and Enumerable

TODO: Complete this.

Docker

Create a container to test things:

docker run --rm -it -h myruby --name myruby -v $(pwd):/myapp ruby:3.2.0 /bin/bash

Rubocop

To disable cops or entire departments in specific places of your codebase:

  • Disable in a section of code:
# rubocop:disable Layout/LineLength, Style
[..]
# rubocop:enable Layout/LineLength, Style
  • Disable all cops in a section of code:
# rubocop:disable all
[..]
# rubocop:enable all
  • Disable cops or departments in a single line:
for x in (0..10) # rubocop:disable Style/For
  • Disable cops or departments using the .rubocop.yml file:
Style/StringLiterals:
  Enabled: false

AllCops:
  Exclude:
    - 'docs/**/'

SQL - PostgreSQL

Spin up a container with PostgreSQL:

docker run --name mypostgresql -d -p 15432:5432 -v mypostgresql:/var/lib/postgresql/data -e POSTGRES_HOST_AUTH_METHOD=trust postgres

Setup Ruby in VSCode

Extensions:

  • vscode-ruby by Peng Lv.
  • Ruby Solargraph by Castwide.
  • Rails Run Specs by Peter Negrei.
  • Go to Spec by Lourenci.
  • Endiwse.
  • ERB Linter.
  • ESLint (for JavaScript code).
  • Auto Close Tag.
  • Github Theme.
  • Material Theme Icons.
  • vscode-gemfile.
  • Ruby Test Explorer.
  • Trailing Spaces.
  • Auto Markdown TOC.
  • VSCode vim, or VSCode Neovim.
  • TODO: For debugging?

Gems:

  • bundler
  • solargraph
  • rubocop

Generate solargraph default config file:

bundle exec solargraph config

Settings file .vscode/settings.json:

{
    "solargraph.useBundler": true,
    "solargraph.checkGemVersion": false,
    "ruby.lint": {
        "rubocop": {
            "useBundler": true
        }
    },
    "ruby.format": "rubocop",
    "ruby.useBundler": true,
    "auto-close-tag.disableOnLanguage": ["markdown"],
    "ruby.specCommand": "bin/rspec",
    "ruby.specFocusTerminal": false,
    "ruby.specSaveFile": true,
    "markdown-toc.depthFrom": 2,
    "files.insertFinalNewline": true
}

Key shortcuts:

  • Go to Spec extension:

    • Go to spec of file: Ctrl + Shift + T.
  • Rails Run Specs extension:

    • Run All Specs: Ctrl + Windows + r.
    • Run File Specs: Ctrl + Windows + t.
    • Run Spec Line: Ctrl + Windows + l.
    • Run Last Spec: Ctrl + Windows + y.