Profiling your SQL queries in hanami (or ROM)

It just happened I had profile SQL query in my hanami application. And I want to save this knowledge that’s why I created this post.

If you are using ROM, this post will be helpful for you too, because hanami-module uses ROM. So, in hanami, you have a simple ability for profiling your SQL queries.

For that, you need to use some methods for Sequel::Dataset instance.

Fox example, if you want to get pure sql sting you can use #sql method:

>> puts UserRepository.new.users.where(admin: true).dataset.sql
SELECT * FROM "users" WHERE ("admin" IS TRUE) ORDER BY "users"."id"
=> nil

or if you need to call ANALYZE or EXPLAIN psql methods you can use similar methods:

>> puts UserRepository.new.users.where(admin: true).dataset.analyze
Sort  (cost=19.38..19.79 rows=165 width=213) (actual time=0.019..0.019 rows=1 loops=1)
  Sort Key: id
  Sort Method: quicksort  Memory: 25kB
  ->  Seq Scan on users  (cost=0.00..13.30 rows=165 width=213) (actual time=0.013..0.014 rows=1 loops=1)
        Filter: (admin IS TRUE)
        Rows Removed by Filter: 1
Planning time: 4.362 ms
Execution time: 0.039 ms
=> nil
>> puts UserRepository.new.users.where(admin: true).dataset.explain
Sort  (cost=19.38..19.79 rows=165 width=213)
  Sort Key: id
  ->  Seq Scan on users  (cost=0.00..13.30 rows=165 width=213)
        Filter: (admin IS TRUE)
=> nil

That’s all, happy profiling! 🚀

Ruby tips #2

It’s a second part of my post series about ruby tips. Today you’ll learn more about:

  • Special values
  • Symbol
  • Array
  • Hash
  • Range

CAUTION: These tips are not equally feat to production. Lots of them are just interesting solutions which you’ll not find anywhere else. Use them at your own risk.

Special values

Safe Levels

Full description

In ruby you can find security levels for your code. The Ruby security level is represented by the $SAFE global variable. The value ranges from minimum value 0 to maximum value 4.

$SAFE Constraints
0 No checking of the use of externally supplied (tainted) data is performed. This is Ruby’s default mode.
>= 1 Ruby disallows the use of tainted data by potentially dangerous operations.
>= 2 Ruby prohibits the loading of program files from globally writable locations.
>= 3 All newly created objects are considered tainted.
>= 4 Ruby effectively partitions the running program in two. Nontainted objects may not be modified. Typically, this will be used to create a sandbox: the program sets up an environment using a lower$SAFE level, then resets $SAFE to 4 to prevent subsequent changes to that environment.

Email Regexp

In ruby you can find regexp for emails. If you want to use it, you have to require uri library and call URI::MailTo::EMAIL_REGEXP constant.

DATA object

The global DATA variable in ruby allows us to access the text at the end of our file listed after the __END__ block. This can be surprisingly useful, for instance if we need to extract information from a rather large data blob.

# in one file
require "json"

puts JSON.load(DATA) # this DATA required text bellow __END__

__END__
{
  "records": [
    {
      "artist":"Iggy Pop",
      "title":"Lust for Life"
    },
    {
      "artist":"Television",
      "title":"Marquee Moon"
    },
    {
      "artist":"Talking Heads",
      "title":"Talking Heads: 77"
    }
  ]
}

Symbol

#all_symbols

Documentation

Return array with all symbols in env.

Symbol.all_symbols.size # => 5675

id2name

Documentation

Alias for #to_s (I don’t know why you need to use this but it’s a funny method I think).

:test.id2name   #=> "test"

slice

Documentation

Alias for sym.to_s[].

:hello_world.slice(0..4) #=> "hello"
:hello_world.[0..4]      #=> "hello"

Array

#bsearch

Documentation

ary = [0, 4, 7, 10, 12]
ary.bsearch {|x| x >=   4 } #=> 4
ary.bsearch {|x| x >=   6 } #=> 7
ary.bsearch {|x| x >=  -1 } #=> 0
ary.bsearch {|x| x >= 100 } #=> nil

Range to array

You can use * operator for converting range to array.

range = (1..10)

range.to_a == [*range] # => true

Hash

** method

You probably know already how to use * in method definition argument list. But ** is less known.

def method_name(value, *attr, **options)
  p attr
  p options
end

method_name('hello', 'cruel', 'world', collor: :red)
# => ['cruel', 'world']
# => { collor: :red }

Also you can call this method like [*attr]

hash = { a: :b, c: :d }

{ **hash, e: :f } # => {:a=>:b, :c=>:d, :e=>:f}

#gsub with hash args

str = "Help! All parentheses have been flipped )and I am sad(!"
str.gsub(/[\(\)]/, {"("=>")", ")"=>"("})
# => "Help! All parentheses have been flipped (and I am sad)!"

Non string and symbol keys

hash = { false => 'No', :to_s.to_proc => 'proc' }

hash[10 < 5]        # => "No"
hash[:to_s.to_proc] # => "proc"

Hash#assoc

This method returns a two element array [key, hash[key]]

{a: 1, b: 2}.assoc(:b) # => [:b, 2]

Range

#cover? and time

((Time.now - 1.hour)..(Time.now + 1.hour)).cover? (Time.now - 1.day) # => false
((Time.now - 1.hour)..(Time.now + 1.hour)).cover? Time.now           # => true

Ranges in case statements

age = 28

case age
when 01..17 then "Young"
when 18..50 then "Adult"
when 50..99 then "Old"
end

Conclusions

That’s all. I hope it’ll be useful for you. In next part we’re gonna talking about:

  • Tracing Ruby Code
  • memory usage
  • Enumerable
  • Compiler
  • Rspec
  • Rails

Happy hacking! 🚀

Ruby tips #1

I’ve been collecting the ruby tips for a long time. And now I’m ready to share them all. Hope you’ll find some interesting solutions, tips and sugars for ruby.

And today we’re talking about:

  • Kernel
  • Class
  • Object
  • Proc (lambda)
  • Method

CAUTION: These tips are not equally feat to production. Lots of them are just interesting solutions which you’ll not find anywhere else. Use them at your own risk.

Kernel

Char

If you want to get string with only one char you can use ?* syntax. Also you can use this hack in various methods like ‘join’

?a == 'a' # => true

[1, 2, 3].join(?:) # => "1:2:3"
[1, 2, 3] * ?: # => "1:2:3"

callcc

You can find callcc method in any language. Ruby is no exception.

caller

Documentation

If you want to return the current execution stack you could use Kernel#caller method.

def a(skip)
  caller(skip)
end

def b(skip)
  a(skip)
end

def c(skip)
  b(skip)
end

c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
c(2)   #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
c(3)   #=> ["prog:13:in `<main>'"]
c(4)   #=> []
c(5)   #=> nil

itself

Ruby went out and got itself an identity method. For those not familiar, an identity method returns the object it’s called on:

1.itself # => 1

j and jj

When you require json library you get two interesting methods. First is Kernel#j. This method outputs object to STDOUT as JSON strings in the shortest form, that is in one line.

require 'json'

h = { a: 1, b: 2 }
j(h)

And second is Kernel#jj This method outputs object to STDOUT as JSON strings in a pretty format, with indentation, and over many lines.

require 'json'

h = { a: 1, b: 2 }
jj(h)

Class

allocate

Documentation

Allocates space for a new object of class’s class and does not call initialize on the new instance. The returned object must be an instance of a class.

class Test
  def initialize
    @var = "new"
  end
end

Test.new      # => #<Test:0x007ff2a34965b8 @var="new">
Test.allocate # => #<Test:0x007ff2a34965b8>

Refinements

Documentation

Usful blog post about refinements

Refinements are designed to reduce the impact of monkey patching on other users of the monkey-patched class. Refinements provide a way to extend a class locally.

module TimeExtensions
  refine Fixnum do
    def minutes; self * 60; end
  end
end

class MyApp
  using TimeExtensions

  def initialize
    p 2.minutes
  end
end

MyApp.new    # => 120
p 2.minutes  # => NoMethodError

Object

tap

Documentation

Yields x to the block, and than returns x.

(1..10)              .tap{ |x| puts "original: #{x.inspect}" }
  .to_a              .tap{ |x| puts "array:    #{x.inspect}" }
  .select{|x| x%2==0}.tap{ |x| puts "evens:    #{x.inspect}" }
  .map{ |x| x * x }  .tap{ |x| puts "squares:  #{x.inspect}" }

Proc (lambda)

curry

Documentation

Ruby defines curry for Method and Proc, allowing procs to return partially applied procs when they get called with fewer than the required number of arguments.

For example:

multiply = -> x,y { x * y }.curry
#=> #<Proc:0x007fed33851510 (lambda)>
multiply[2,3]
#=> 6
double = multiply[2]
#=> #<Proc:0x007fed35892888 (lambda)>
double[3]
#=> 6

Note: While Proc#curry has been around since Ruby 1.9, Method#curry was only added in Ruby 2.2.0. For versions before 2.2.0, you will first need to convert your method object to a proc via Method#to_proc.

#to_proc and #method

Documentation

If you need call method with args in to_proc you can use method method:

[:asd, :bsd].map{ |i| puts i }
# it's like as
[:asd, :bsd].map(&method(:puts))

All ways to call proc (lambda)

You can use 7 different ways to call lambda:

p = -> { "hello" }

p.call()
p::()
p.()
p[]
p.yield
p.===
p.send(:call)

Method

method

You can call some methods with method method. This method returns Method class. And after that you’re just calling this object like simple proc object:

# 'method' method
sin_method = Math.method(:sin)
(1..10).map(&sin_method)

# lambda style
sin_method = -> (x) { Math.sin(x) }
(1..10).map(&sin_method)

Block

Empty block

>> [1, 2, 3].map
# => #<Enumerator: [1, 2, 3]:map>

# or
>> [1, 2, 3].map(&nil)
# => #<Enumerator: [1, 2, 3]:map>

You can send &nil as an empty block.

Conclusions

That’s all. I hope it’ll be useful for you. In next part we’re gonna talking about:

  • Special values in ruby world
  • Symbol
  • Array
  • Hash
  • Range

Happy hacking! 🚀

Adding domain for your github project

I have a problem. Each time I want add domain to my custom github project I forget what I should do exactly. That’s why I want to post this SO answer in my blog. I hope it would helpful not only for me.

To Setup a custom domain for your gh-pages project repo that handles www.yourdomain.com and yourdomain.com (assumes you already have a gh-pages branch on your repo) you need this:

  1. From your project repo, gh-pages branch. Create a CNAME file with the contents yourdomain.com.
  2. In your DNS manager, setup two CNAME records. One for the root apex (@) and one for www. Both point to YOURusername.github.io. If your DNS provider does NOT support ALIAS records on the root apex (@), simply create A records that point to 192.30.252.153 and 192.30.252.154.

After that wait til your name servers update:

dig yourdomain.com +nostats +nocomments +nocmd


Original link: stackoverflow.com/a/9123911

Preview hanami emails in browser

Sometimes you need to preview your emails in development enviroment. For this you can use use letter_opener gem. Because hanami uses mail gem, letter_opener integration will be easy. Firstly you need add gem to your Gemfile:

gem "letter_opener", group: :development

Secondly you need add new delivery method to your lib/repository_name.rb file:

require "letter_opener"
Hanami::Mailer.configure do
  delivery do
    development LetterOpener::DeliveryMethod, location: Hanami.root.join('tmp/letter_opener')
  end
end.load!

After that when you deliver your email, letter_opener will generate html files that users will see in tmp/letter_opener directory.

Building your rails API with roda

Introduction

Sometimes you need to build API serveice in your rails application. Of course you can use popular solutions as grape or rails-api gems. And also you can find real examples in gitlab or rubygems projects.

But today I’m going to tell you about other framework. It’s roda. Roda was created by Jeremy Evans and it’s fast and simple ruby routing framework. So why should you take a look on it?

There’s a list of advantages of this framework:

  1. Fast;
  2. Simple;
  3. Roda provides simple way to working with big count of different plugins;
  4. You can use any architecture with it;

So I mentioned that roda is fast. If you want to verify this, just check this benchmark repository and you’ll see that roda is really fast. For example, I run benchmarks on locally and get this result:

Framework            Requests/sec  % from best
----------------------------------------------
mustermann                9389.60       100.0%
roda                      9252.03       98.53%
rack                      9246.16       98.47%
hanami-router             6240.81       66.47%
sinatra                   2935.63       31.26%
grape                     2512.17       26.75%

Integration

Roda based on rack. That’s why this integration with rails will be very simple. Firstly you need to add roda gem to your gemfile:

gem 'roda'

Secondly you need to create simple roda application. Note that you need to use json and all_verbs plugins. The first one needs to JSON responce and the second one provides all REST methods for your application (like put, patch, etc). I puted my roda application in to lib/api/base.rb path but you can use whatever you waht.

# lib/api/base.rb
require 'roda'
require 'json'

module API
  class Base < Roda
    plugin :json
    plugin :all_verbs

    route do |r|
      r.on "v1" do
        r.get 'hello' do
          { hello: :world }
        end
      end
    end
  end
end

After that you need to mount your application in config/routes.rb. This is done as well as any other rack application:

# config/routes.rb
require './lib/api/base'
mount API::Base => '/api'

And the last part, we need to split our application to different modules with different logic and routes. For this we have to create required module. In an example I created Users module with all REST routes:

# lib/api/users.rb
module API
  class Users < Roda
    plugin :json
    plugin :all_verbs

    route do |r|
      r.is 'users' do
        r.get do
          { users: User.last(10) }
        end

        r.post do
          { user: User.new }
        end
      end

      r.is 'users/:id' do |id|
        user = User.find(id)

        r.get do
          { user: user}
        end

        r.patch do
          { user: 'updated' }
        end

        r.delete do
          { user: 'deleted' }
        end
      end
    end
  end
end

Finnaly you need to mount our module to roda application. It is very simple too.

# lib/api/base.rb
require 'roda'
require 'json'
require 'users'

module API
  class Base < Roda
    plugin :json
    plugin :all_verbs

    route do |r|
      r.on "v1" do
        r.run API::Users
      end
    end
  end
end

That’s all. Now we have a simple roda API application which integrated to our rails app.

Problems / future

In the last part I want to list problems and ideas what I want to solve in future.

  1. Roda doesn’t have a swagger integrating from the box. Now I’m thinking about using swagger-block gem for it.
  2. Also roda doesn’t typecast your params. I know that grape uses virtus gem for this. And this feature you should realize by youself too.

Conclusion

On this blog post I wanted to show you that you’re not limited only to popular API server gems. As you can see roda have amazing ideas and properties such as modulatiry, simplicity, speed and stability. Also this framework has a simple way to integration in to your rails application.

Happy hacking! emoji

Further reading

Adding anchors to your middleman project

All people love anchors. It’s helpful, cool and practical. If you want to add anchors to you middleman project you need to follow the following steps.

First: we need to create a new renderer class. In this class we’ll put <a> tag inside <h> tag. Also, we’ll realize anchor svg in guthub style:

require 'middleman-core/renderers/redcarpet'

class GithubStyleTitles < Middleman::Renderers::MiddlemanRedcarpetHTML
  def header(title, level)
    @headers ||= []
    permalink = title.gsub(/\W+/, '-')

    if @headers.include? permalink
      permalink += '_1'
      permalink = permalink.succ while @headers.include? permalink
    end
    @headers << permalink

    %(
      <h#{level} id=\"#{permalink}\" class="title">
        <a name="#{permalink}" class="anchor" href="##{permalink}"></a>
        #{title}
      </h#{level}>
    )
  end

private

  def anchor_svg
     <<-eos
       <svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16">
       <path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path>
       </svg>
     eos
  end
end

After that we need to call our renderer in :markdown configuration:

set :markdown, fenced_code_blocks: true, smartypants: true, renderer: GithubStyleTitles

And the last step: we need to stylize our anchor with css:

.anchor {
  padding-right: 2px;
  margin-left: -18px;
  display: none;
}
.title .anchor {
  display: inline-block;
}

After all this steps we’ll get something like this:

gif

I hope it will be useful to you as well as for me at one time.

Happy hacking! 💚

Simplest way to authenticate user in hanami app

If you need the simplest and easiest way to adding authentication logic in your hanami app (to admin app for example) you always can use Rack::Auth::Basic class.

For this you need to add following lines of code to your controller.prepare configuration block:

# apps/admin/application.rb

controller.prepare do
  # ...
  # some code

  use Rack::Auth::Basic, 'Message' do |username, password|
    username == 'admin' && password == 'password'
  end
end

Happy authenticating!

P.S.: also if you need something more complicated you can reed this thread on hanami forum.

Profiling minitest examples with Stackprof

Today I read a nice blog post by Kir Shatrov about Profiling RSpec examples with Stackprof and I wondered if I could repeat this trick with minitest? This question is very important for me because I ofen use minitest for my job and OSS projects. Also a lot of cool projects use minitest (for example, sidekiq, rails, lotus, etc).

In reality, to do that in minitest as easy as in RSpec, and the only difference is that you need to install a separate gem.

  1. Firstly you have to install minitest-around gem;
  2. And secondly you have to add this block of code to your test_helper file;
# test/test_helper.rb
require 'stackprof'
require 'minitest/around/spec'

class Minitest::Test
  def around(&example)
    path = "path/to/repo/tmp/stackprof.dump"
    StackProf.run(mode: :object, out: path.to_s) do
      example.call
    end
  end
end

Happy profiling!

Rendering ruby block result in layout file

If you want to render some result of ruby block in your layout file, you may run into some problems. For example, your result may be repeated on page or you can get something worse.

let’s assume we have these methods:

def add_to_head(&block)
  @head_html ||= []
  @head_html << block if block_given?
end

def display_custom_head
  return unless @head_html
  @head_html.map(&:call).join
end

Of cource you can use captire method from rails and sinatra-contrib librares. But what will you do if you can’t use these methods or you need something easier?

I faced a similar problem (for example, in sidekiq) and I used own capture method for layout files.

def capture(&block)
  block.call
  eval('', block.binding)
end

And after that we can update our display_custom_head method:

def display_custom_head
  return unless @head_html
  @head_html.map { |block| capture(&block) }.join
end

I hope it will be useful to you as well as for me at one time.

Happy hacking!