Mind Dump, Tech And Life Blog
written by Ivan Alenko

Ruby on Rails Random Notes

Use FactoryBot from development rails console

include FactoryBot::Syntax::Methods
include ActionDispatch::TestProcess

Redis not running or wrong host

Errno::EADDRNOTAVAIL (Cannot assign requested address - connect(2) for [::1]:6379

Redis isn’t running on localhost. Set environment variable REDIS_URL to real address like redis://redis:6379/0.

Url helper requires a URL

ActionView::Template::Error (Nil location provided. Can't build URI.)URL cannot be nil for some URL helpers in Rails.

Solution 1: Use default cover image:

image_tag(@article.cover.url || default_cover_url)

Solution 2: Don’t show any cover image if it’s not there

<% if @article.cover %>
  image_tag(@article.cover.url)
<% end %>

Webpacker In Rails Engine Doesn’t Work

Webpacker in Rails 6.0.3 engines is not integrated very well. I mean spend two weeks configuring webpack and it might work. And will be coupled. I tried to follow three guides, but two of them had serious limitations and one didn’t work.

Failures:

  1) welcome page shows articles
     Failure/Error: <%= stylesheet_pack_tag 'application', media: 'all' %>

     ActionView::Template::Error:
       undefined method `stylesheet_pack_tag' for #<#<Class:0x00007f9678134ca8>:0x00007f967813f3b0>
       Did you mean?  stylesheet_path
                      stylesheet_link_tag
     # ./spec/dummy/app/views/layouts/application.html.erb:10:in `_app_views_layouts_application_html_erb__3341715273681785289_70142118227440'
     # ./spec/requests/welcome_spec.rb:6:in `block (3 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # NoMethodError:
     #   undefined method `stylesheet_pack_tag' for #<#<Class:0x00007f9678134ca8>:0x00007f967813f3b0>
     #   Did you mean?  stylesheet_path
     #                  stylesheet_link_tag
     #   ./spec/dummy/app/views/layouts/application.html.erb:10:in `_app_views_layouts_application_html_erb__3341715273681785289_70142118227440'

Finished in 0.50944 seconds (files took 3.19 seconds to load)
10 examples, 1 failure

How to Run Sidekiq

Command to run Sidekiq from application directory.

bundle exec sidekiq

Inspecting Network Traffic In Capybara Driver

I think this was Apparition, Chrome Headless. Useful command because sometimes weird shit happens.

puts page.driver.network_traffic.map{|traffic| [traffic.url, traffic.method, traffic.response&.status, traffic.error&.code, traffic.error&.description]}.inspect

Inspecting Sidekiq Queues Directly With Redis Commands

Because sometimes Sidekiq interface is not available. Commands are specific for types, therefore the most important thing is to list data and it’s type. Using from Redis CLI will be similar.

# rails console
r = Redis.new

# list keys
pp r.keys.select{|k| k !~ /stat/ }.map{|k| [k, r.type(k)]}; nil
[["queue:api", "list"],
 ["dead", "zset"],
 ["queues", "set"],
 ["retry", "zset"],
 ["ec5ec2a0e9d3:1:fe1000f40d66", "hash"],
 ["processes", "set"],
 ["schedule", "zset"]]
=> nil

r.hgetall "ec5ec2a0e9d3:1:fe1000f40d66"
=> {"quiet"=>"false", "info"=>"{\"hostname\":\"ec5ec2a0e9d3\",\"started_at\":1579787753.5046794,\"pid\":1,\"tag\":\"app\",\"concurrency\":25,\"queues\":[\"default\",\"mailers\"],\"labels\":[],\"identity\":\"ec5ec2a0e9d3:1:fe1000f40d66\"}", "beat"=>"1579791952.047832", "busy"=>"0"}

r.lrange "queue:api", 0, 100
=> ["{\"class\":\"ApiWorker\",\"args\":[\"26\"],\"retry\":true,\"queue\":\"api\",\"throttle\":{\"threshold\":4,\"period\":\"15\"},\"backtrace\":true,\"jid\":\"e7b7ca29e568cf1a1fd2570a\",\"created_at\":1562264868.547173,\"enqueued_at\":1562264879.8490522}", "{\"class\":\"ApiWorker\",\"args\":[\"30\"],\"retry\":true,\"queue\":\"api\",\"throttle

r.smembers "processes"
=> ["ec5ec2a0e9d3:1:fe1000f40d66"]

r.smembers "queues"
=> ["default", "mailers", "api"]

LOADING Redis is loading the dataset in memory (Redis::CommandError)

/usr/local/bundle/gems/redis-4.1.4/lib/redis/client.rb:126:in `call': LOADING Redis is loading the dataset in memory (Redis::CommandError)

This really means Redis is still loading data. If Redis is running in --append-only mode, database file (appendonly.aof) will only get larger until it has couple of gigabytes or more and takes couple of minutes to load.

Needs to be compacted regularly, to get rid of old data.

redis-cli
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

It will compact couple of gigabytes into couple of megabytes. For Rails app.

Debug Session in a Controller or View

You can’t just inspect session object since it contains lots of crap added by middlewares. To see only keys from session cookie do this:

puts 'SESSION', session.keys.reduce([]) {|result, key| result << [key, session[key]]}.inspect

Remove All Precompiled Assets

RAILS_ENV=staging NODE_ENV=production bin/rails tmp:clear assets:clobber
RAILS_ENV=staging NODE_ENV=production bin/rails assets:precompile

Or just remove public/assets and public/packs and sprockets cache in tmp/. Useful when recompiling assets on staging for some reason or get rid of precompiled assets in development environment (once precompiled, Rails will ignore changes to assets).

Cannot Rollback Named Database in Rails 6+

As far as I know it’s not possible in 6.x. Do it by hand - do the changes manually and remove migration number from table schema_migrations.

user@starz:~/current$ RAILS_ENV=production bin/rails db:rollback:oni_sorceress STEP=1
rails aborted!
Don't know how to build task 'db:rollback:oni_sorceress' (See the list of available tasks with `rails --tasks`)
Did you mean?  db:create:oni_sorceress
               db:drop:oni_sorceress
               db:migrate:oni_sorceress
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/railties-6.0.3.4/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/railties-6.0.3.4/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/railties-6.0.3.4/lib/rails/command.rb:48:in `invoke'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/railties-6.0.3.4/lib/rails/commands.rb:18:in `<main>'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `block in require'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
/home/myrtana_sk/shared/bundle/ruby/2.7.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `require'
bin/rails:9:in `<main>'
(See full trace by running task with --trace)

Irb Bring Back Seeing Variable Value After Assign

Irb won’t echo the variable value since 2.7.2. Add this to or create a new file ~/.irbrc. I don’t like it and when debugging in production, I learned to add ;nil to .each.

IRB.conf[:ECHO_ON_ASSIGNMENT] = true

Postgres PG::UniqueViolation - Duplicate Key

Error:

ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "articles_pkey")
DETAIL:  Key (id)=(101) already exists.

Go to Rails console and type:

ActiveRecord::Base.connection.reset_pk_sequence!('articles')

Where the parameter is more less the name of the index (on field).

Ambiguous match, found 2 elements matching visible xpath “/html”

  4) some test
     Failure/Error: expect(page).to have_content('foo')

     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching visible xpath "/html"

The problem is there is HTML code after </html> tag.

Rails 6 Generate Polymorphic Migration For Named Database

--db option

bin/rails g model PrivateImage private_imageable:references{polymorphic} body:blob metadata:jsonb --db oni_sorceress