Thursday, March 31, 2016

Installing libv8 on Mac OS

Problem:

xcode-select: Error: No Xcode folder is set. Run xcode-select -switch to set the path to the Xcode folder.

Resolution:

xcode-select --print-path
sudo xcode-select -switch /Developer-3.2.6/Applications/Xcode.app/Contents/MacOS/
gem install therubyracer -v 0.12.2


Rails 5 Generator Help

$rails g helper --help

Usage:
  rails generate generator NAME [options]

Options:
      [--skip-namespace], [--no-skip-namespace]  # Skip namespace (affects only isolated applications)
      [--namespace], [--no-namespace]            # Namespace generator under lib/generators/name
                                                 # Default: true
  -t, [--test-framework=NAME]                    # Test framework to be invoked
                                                 # Default: test_unit

Runtime options:
  -f, [--force]                    # Overwrite files that already exist
  -p, [--pretend], [--no-pretend]  # Run but do not make any changes
  -q, [--quiet], [--no-quiet]      # Suppress status output
  -s, [--skip], [--no-skip]        # Skip files that already exist

Description:
    Stubs out a new generator at lib/generators. Pass the generator name as an argument,
    either CamelCased or snake_cased.

Example:
    `rails generate generator Awesome`

    creates a standard awesome generator:
        lib/generators/awesome/
        lib/generators/awesome/awesome_generator.rb
        lib/generators/awesome/USAGE
        lib/generators/awesome/templates/
        test/lib/generators/awesome_generator_test.rb

Rails 5 Available Generators

Usage: rails generate GENERATOR [args] [options]

General options:
  -h, [--help]     # Print generator's options and usage
  -p, [--pretend]  # Run but do not make any changes
  -f, [--force]    # Overwrite files that already exist
  -s, [--skip]     # Skip files that already exist
  -q, [--quiet]    # Suppress status output

Please choose a generator below.

Rails:
  assets
  channel
  controller
  generator
  helper
  integration_test
  jbuilder
  job
  mailer
  migration
  model
  resource
  scaffold
  scaffold_controller
  task

Coffee:
  coffee:assets

Js:
  js:assets

Kaminari:
  kaminari:config
  kaminari:views

RailsFootnotes:
  rails_footnotes:install

TestUnit:
  test_unit:generator
  test_unit:plugin

ValidatesTimeliness:
  validates_timeliness:install

Tuesday, March 29, 2016

Generating a URL from non sanitized request parameters is insecure!

Kaminari with Rails 5 use:

gem 'kaminari', :git => "git://github.com/amatsuda/kaminari.git", :branch => 'master'

ive_support/i18n_railtie.rb:45:in `map':

will_paginate 3.0.7 is not compatible with Rails 5. Upgrade to will_paginate 3.1.

Friday, March 25, 2016

How to pass custom variables to a partial in Rails 5

Let's say that you want to render the same form partial for creating and editing a project. You can pass a custom value for the button in the form partial like this:

<%= render 'form', project: @project, button_name: 'Create'  %>



You can use the passed in variable in the form partial like this:



<%= form_for(project) do |f| %>
  <% if project.errors.any? %>
   

     

<%= pluralize(project.errors.count, "error") %> prohibited this project from being saved:



     

          <% project.errors.full_messages.each do |message| %>
           
  • <%= message %>

  •       <% end %>
         

   

  <% end %>

    <% if params[:preview_button] %>
      <%= project.description %>
    <% end %>

 

    <%= f.label :name %>
    <%= f.text_field :name %>
 


 

    <%= f.label :description %>
    <%= f.text_area :description %>
 


 

    <%= f.submit button_name %>
    <%= f.submit 'Preview', name:  'preview_button'  %>
   
 

<% end %>

Wednesday, March 23, 2016

Problem Installing libv8 and therubyracer on El Capitan

Error:

.rvm/gems/ruby-2.3.0@blog/gems/libv8-3.16.14.7/ext/libv8/location.rb:36:in `block in verify_installation!': libv8 did not install properly, expected binary v8 archive '/.rvm/gems/ruby-2.3.0@blog/gems/libv8-3.16.14.7/vendor/v8/out/x64.release/obj.target/tools/gyp/libv8_base.a'to exist, but it was not found (Libv8::Location::Vendor::ArchiveNotFound)

Resolution:

brew install v8
gem install libv8 -v '3.16.14.7' -- --with-system-v8
bundle update therubyracer


Tuesday, March 22, 2016

How to create a new Rails 5 app

1. gem install rails --pre --no-ri --no-rdoc

2. rails new app-name

How to handle routing errors in Rails 4.2.6

    Step 1
   
    In routes.rb:
   
    match '*unmatched_route', :to => 'application#handle_routing_error', :via => :all
   
    Step 2
   
In application_controller.rb:

    rescue_from ActionController::RoutingError, :with => :handle_routing_error

    def handle_routing_error
      logger.info "No route matches #{params[:unmatched_route]}"
      render nothing: true
    end

Turn on logging to see remote calls made in ActiveResource

ActiveResource::Base.logger = ActiveRecord::Base.logger

Sunday, March 20, 2016

Find the most popular end points in your Rails apps


grep "Parameters:" log/production.log | grep -o '".*"' | sed --r 's/[[:digit:]]*/:id/' | sort | uniq -c

to exclude certain things, pipe to grep -v 'string to exclude'

Saturday, March 19, 2016

Rails Footnotes Gem





Cloudfront favicon error in Rails 4.2.6

[Chrome] [2016-03-18 04:19:04.221] [56b01676-4491-4c4e-9458-666168fb7267] [info] [d1b5oz78c0udqh.cloudfront.net] [182.96.98.1] [session_id : None] [PID-12309] 
ActionController::RoutingError (No route matches [GET] "/favicon.ico"):
  actionpack (4.2.6) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  actionpack (4.2.6) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.2.6) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.2.6) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.6) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.6) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.6) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.6) lib/rails/rack/logger.rb:20:in `call'
  actionpack (4.2.6) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.4) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.4) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.6) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  rack (1.6.4) lib/rack/sendfile.rb:113:in `call'
  actionpack (4.2.6) lib/action_dispatch/middleware/ssl.rb:24:in `call'
  railties (4.2.6) lib/rails/engine.rb:518:in `call'
  railties (4.2.6) lib/rails/application.rb:165:in `call'
  passenger (5.0.25) src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
  passenger (5.0.25) src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:152:in `accept_and_process_next_request'
  passenger (5.0.25) src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:113:in `main_loop'
  passenger (5.0.25) src/ruby_supportlib/phusion_passenger/request_handler.rb:416:in `block (3 levels) in start_threads'
  passenger (5.0.25) src/ruby_supportlib/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'

Resolution:

In layout file use this:

  <%= favicon_link_tag 'favicon.ico' %>

instead of:

  <%= favicon_link_tag  %>

Thursday, March 17, 2016

SQLite3::ReadOnlyException: attempt to write a readonly database

This happened when the rake tasks were run in one command:

rake db:drop db:migrate db:seed

Solution: Run the commands individually.

List the files that were changed between two branches in Git

 git diff --name-status master..branch-name

Pimp My RailsCasts Series

1. Caching with Instance Variables
2. Dynamic find_by Methods
3. Find Through Association
4. Move Find into Model
5. Using with_scope
6. Shortcut Blocks with Symbol to_proc
7. All About Layouts
8. Layouts and content_for
9. Filtering Sensitive Logs
10. Refactoring User Name Part 1
11. Refactoring User Name Part 2
12. Refactoring User Name Part 3
13. Dangers of Model in Session
14. Performing Calculations on Models
15. Fun with Find Conditions
16. Virtual Attributes
17. HABTM Checkboxes
18. Looping Through Flash
19. Where Administration Goes - Not revised
20. Restricting Access - Not revised
21. Super Simple Authentication - Not revised
22. Eager Loading - Coming soon
23. Counter Cache Column
24. The Stack Trace
25. SQL Injection
26. Hackers Love Mass Assignment
27. Cross Site Scripting
28. in_groups_of
29. group_by Month
30. Pretty Page Title
31. Formatting Time
32. Time in Text Field
33. Making a Plugin
34. Named Routes

Tuesday, March 15, 2016

Rails 5 New Project Options

$ rails new --help
Usage:
  rails new APP_PATH [options]

Options:
  -r, [--ruby=PATH]                                      # Path to the Ruby binary of your choice
                                                         # Default: /Users/bparanj/.rvm/rubies/ruby-2.3.0/bin/ruby
  -m, [--template=TEMPLATE]                              # Path to some application template (can be a filesystem path or URL)
  -d, [--database=DATABASE]                              # Preconfigure for selected database (options: mysql/oracle/postgresql/sqlite3/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)
                                                         # Default: sqlite3
  -j, [--javascript=JAVASCRIPT]                          # Preconfigure for selected JavaScript library
                                                         # Default: jquery
      [--skip-gemfile], [--no-skip-gemfile]              # Don't create a Gemfile
  -B, [--skip-bundle], [--no-skip-bundle]                # Don't run bundle install
  -G, [--skip-git], [--no-skip-git]                      # Skip .gitignore file
      [--skip-keeps], [--no-skip-keeps]                  # Skip source control .keep files
  -M, [--skip-action-mailer], [--no-skip-action-mailer]  # Skip Action Mailer files
  -O, [--skip-active-record], [--no-skip-active-record]  # Skip Active Record files
  -P, [--skip-puma], [--no-skip-puma]                    # Skip Puma related files
  -C, [--skip-action-cable], [--no-skip-action-cable]    # Skip Action Cable files
  -S, [--skip-sprockets], [--no-skip-sprockets]          # Skip Sprockets files
      [--skip-spring], [--no-skip-spring]                # Don't install Spring application preloader
      [--skip-listen], [--no-skip-listen]                # Don't generate configuration that depends on the listen gem
  -J, [--skip-javascript], [--no-skip-javascript]        # Skip JavaScript files
      [--skip-turbolinks], [--no-skip-turbolinks]        # Skip turbolinks gem
  -T, [--skip-test], [--no-skip-test]                    # Skip test files
      [--dev], [--no-dev]                                # Setup the application with Gemfile pointing to your Rails checkout
      [--edge], [--no-edge]                              # Setup the application with Gemfile pointing to Rails repository
      [--rc=RC]                                          # Path to file containing extra configuration options for rails command
      [--no-rc], [--no-no-rc]                            # Skip loading of extra configuration options from .railsrc file
      [--api], [--no-api]                                # Preconfigure smaller stack for API only apps

Runtime options:
  -f, [--force]                    # Overwrite files that already exist
  -p, [--pretend], [--no-pretend]  # Run but do not make any changes
  -q, [--quiet], [--no-quiet]      # Suppress status output
  -s, [--skip], [--no-skip]        # Skip files that already exist

Rails options:
  -h, [--help], [--no-help]        # Show this help message and quit
  -v, [--version], [--no-version]  # Show Rails version number and quit

Description:
    The 'rails new' command creates a new Rails application with a default
    directory structure and configuration at the path you specify.

    You can specify extra command-line arguments to be used every time
    'rails new' runs in the .railsrc configuration file in your home directory.

    Note that the arguments specified in the .railsrc file don't affect the
    defaults values shown above in this help message.

Example:
    rails new ~/Code/Ruby/weblog

    This generates a skeletal Rails installation in ~/Code/Ruby/weblog.

Wednesday, March 09, 2016

Symbol to_proc Hack

Usually, when we create a proc, the proc object captures the variables that is in the creation context. However, in Symbol#to_proc,  the object obj that is in:

Proc.new {|obj| obj.send(self) }

is not in the surrounding context of the proc object. At this point there is no 'obj' object. So, within the Symbol class to_proc method, there is no obj. When the & ampersand trigger is executed, the map method yields a block variable, this block variable gets associated to the obj object. This is a subtle concept. We can bind values to the block variable in the proc object at run-time. This is a very powerful concept we can use when we develop libraries.


Tuesday, March 08, 2016

Trace Route on Mac OS

$ traceroute www.rubyplus.com

traceroute to www.rubyplus.com (198.58.102.13), 64 hops max, 52 byte packets
 1  10.33.0.1 (10.33.0.1)  0.760 ms  0.245 ms  0.252 ms
 2  209.133.4.85 (209.133.4.85)  0.456 ms  0.522 ms  0.516 ms
 3  ae5.cr2.sjc2.us.zip.zayo.com (64.125.26.21)  2.386 ms  4.013 ms  3.053 ms
 4  ae16.mpr4.sjc7.us.zip.zayo.com (64.125.31.15)  1.757 ms  1.909 ms  1.868 ms
 5  209.133.4.46 (209.133.4.46)  1.914 ms  1.945 ms  1.971 ms
 6  ae0.bbr02.cs01.lax01.networklayer.com (173.192.18.151)  10.292 ms  10.630 ms  10.217 ms
 7  ae7.bbr01.cs01.lax01.networklayer.com (173.192.18.166)  10.367 ms  10.220 ms  10.698 ms
 8  ae19.bbr01.eq01.dal03.networklayer.com (173.192.18.140)  40.263 ms  37.674 ms  40.394 ms
 9  po31.dsr02.dllstx3.networklayer.com (173.192.18.227)  38.005 ms  37.520 ms  40.913 ms
10  po32.dsr02.dllstx2.networklayer.com (70.87.255.70)  41.327 ms  37.968 ms
    po31.dsr01.dllstx2.networklayer.com (70.87.255.66)  40.557 ms
11  po1.car02.dllstx2.networklayer.com (70.87.254.82)  37.646 ms
    po2.car01.dllstx2.networklayer.com (70.87.254.78)  37.714 ms
    po2.car02.dllstx2.networklayer.com (70.87.254.86)  41.112 ms
12  router2-dal.linode.com (67.18.7.94)  37.950 ms  40.729 ms
    router1-dal.linode.com (67.18.7.90)  41.317 ms
13  www.rubyplus.com (198.58.102.13)  41.468 ms  41.386 ms  37.602 ms

Dependency Inversion Principle Example from The RSpec Book

The code example for Codebreaker game from The Rspec Book. The solution in the book that does not apply the DIP

Before

module Codebreaker
  class Game
    def initialize(output)
      @output = output
    end

    def start(secret)
      @secret = secret
      @output.puts 'Welcome to Codebreaker!'
      @output.puts 'Enter guess:'
    end
  end
end

g = Codebreaker::Game.new($stdout)
g.start('sekret')

The solution after applying the DIP.

After

module Codebreaker
  class Game
    def initialize(writer)
      @writer = writer
    end

    def start(secret)
      @secret = secret
      @writer.write 'Welcome to Codebreaker!'
      @writer.write 'Enter guess:'
    end
  end
end

class StandardConsole
  def write(message)
    $stdout.puts(message)
  end 
end

writer = StandardConsole.new
g = Codebreaker::Game.new(writer)
g.start('sekret')

List Untracked Files in Git

git ls-files --others --exclude-standard

You can chain this to xargs:

git ls-files --others --exclude-standard | xargs git rm

to remove those files.

Monday, March 07, 2016

Dependency Inversion Principle

The article

The Three Basic Rules for a Good Design

illustrates the Dependency Inversion Principle in action by using a simple example. It applies three simple rules:

  1. Separate things that change from things that stays the same. Encapsulate what varies behind a well-defined interface.
  2. Program to interfaces, not implementations. This exploits polymorphism.
  3. Depend on abstractions. Do not depend on concrete classes.
to satisfy Dependency Inversion Principle. 

Storage mechanisms such as PersonMemoryStore and PersonFileStore have a well defined interface called records. The mechanisms to send the message such as GreetingConsole and GreetingPony have a well defined interface call send. Classes that implement a specific storage or sending email now conform to a uniform interface. This gives us the ability to switch implementation in different combinations. The classes that implement specific way of doing things depend on stable abstractions, records and send that we came up with in the final design.

Saturday, March 05, 2016

Compress Custom Web Fonts in Rails 4.2.5 Apps

 The easiest way to compress custom web fonts in a Rails 4.2.5 app is to use Amazon Cloudfront. In your Cloudfront configuration, select Yes for Compress Objects Automatically.


Here you can see the result of Web Page Performance Test for RubyPlus after the Custom Web fonts has been compressed. It takes 30 minutes or so for the cloudfront configuration changes to take effect.

Amazon Docs

Friday, March 04, 2016

Caching Database Results in Rails 4.2.5

If you make the same database calls  within any one request, Rails will cache the database result. You don't need to use use ||= to cache the value.
  def show
    Article.find(params[:id])
    Article.find(params[:id])
  end

You can see that the cache is hit in the log file:

Started GET "/articles/1" for ::1 at 2016-03-03 16:42:13 -0800
Processing by ArticlesController#show as */*
  Parameters: {"id"=>"1"}
  Article Load (0.1ms)  SELECT  "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1  [["id", 1]]
  CACHE (0.0ms)  SELECT  "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1  [["id", "1"]]
  Rendered articles/show.html.erb within layouts/application (0.3ms)
Completed 200 OK in 25ms (Views: 24.0ms | ActiveRecord: 0.1ms)

From  the Caching with Rails guide.

SQL Caching

Query caching is a Rails feature that caches the result set returned by each query so that if Rails encounters the same query again for that request, it will use the cached result set as opposed to running the query against the database again.

Thursday, March 03, 2016

Compress all Assets using GZip

In production.rb:

use Rack::Deflater

https://remino.net/rails-html-css-js-gzip-compression/

Wednesday, March 02, 2016

Compress Html to Improve Rails 4.2.5 App Performance

1. Add htmlcompressor gem to Gemfile.

group :production do
  gem 'htmlcompressor'
end

Run bundle install.

2. In production.rb:

  config.middleware.use HtmlCompressor::Rack

3. Deploy and enjoy the speed.


GTmetrix.com test score for html compression went up. But the performance went down. The page load time went up to 2.1 seconds from 1.7 seconds.

Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.

This error happens if any of the directory in which you are running rails new has some rails directory structure. Resolution: Go to a directory that does not have any rails directory structure.

Can the genius Rails committers provide the resolution as part of the error message please?

Tuesday, March 01, 2016

Using Asset Pipeline for Favicons in Rails 4.2.5

1. Copy icon images to app/assets/images folder.

2. Use favicon_link_tag helper. Default image name : favicon.ico.
   
      <%= favicon_link_tag %>
  <%= favicon_link_tag 'apple-touch-icon-57x57.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "57x57" %>
  <%= favicon_link_tag 'apple-touch-icon-60x60.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "60x60" %>
  <%= favicon_link_tag 'apple-touch-icon-72x72.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "72x72" %>
  <%= favicon_link_tag 'apple-touch-icon-76x76.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "76x76" %>
  <%= favicon_link_tag 'apple-touch-icon-114x114.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "114x114" %>    
  <%= favicon_link_tag 'apple-touch-icon-120x120.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "120x120" %>
  <%= favicon_link_tag 'apple-touch-icon-144x144.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "144x144" %>
  <%= favicon_link_tag 'apple-touch-icon-152x152.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "152x152" %>
  <%= favicon_link_tag 'apple-touch-icon-180x180.png', rel: 'apple-touch-icon', type: 'image/png', sizes: "180x180" %>
  <%= favicon_link_tag 'favicon-32x32.png', rel: 'icon', type: 'image/png', sizes: "32x32" %>          
  <%= favicon_link_tag 'android-chrome-192x192.png', rel: 'icon', type: 'image/png', sizes: "192x192" %>          
  <%= favicon_link_tag 'favicon-96x96.png', rel: 'icon', type: 'image/png', sizes: "96x96" %>          
  <%= favicon_link_tag 'favicon-16x16.png', rel: 'icon', type: 'image/png', sizes: "16x16" %>            


3. Verify by viewing the page source.

  <link rel="shortcut icon" type="image/x-icon" href="https://d1b5oz78c0udqh.cloudfront.net/assets/favicon-0784d42434f39fe96f3736f3e47d1e9f.ico" />
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-57x57-1f87fa73399b81c63cf77fee620b3f25.png" sizes="57x57" />
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-60x60-421e797d9dc30906f3876c0bf72c8e98.png" sizes="60x60" />
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-72x72-53f33feccdeb7a9428d3bfd3f9fdcb5c.png" sizes="72x72" />  
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-76x76-8d6db4af70c6c952ffbc34e742035187.png" sizes="76x76" />  
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-114x114-308d3819dfb621285ab6368f672a72fb.png" sizes="114x114" />      
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-120x120-15eedd3461f483a5b27828fa9ed789de.png" sizes="120x120" />  
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-144x144-5759a401867e2dfe239149695d7cd081.png" sizes="144x144" />  
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-152x152-9f15e1c9218a79ee781a128e8bfba79a.png" sizes="152x152" />  
  <link rel="apple-touch-icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/apple-touch-icon-180x180-2fc81325eec91ad63efb7d10ae0e1089.png" sizes="180x180" />  
  <link rel="icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/favicon-32x32-e6eebf5633792e63508f58260cfc98c6.png" sizes="32x32" />            
  <link rel="icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/android-chrome-192x192-b03a39be430b547b8448857ef3ed1960.png" sizes="192x192" />            
  <link rel="icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/favicon-96x96-93f5bc8d5e587ff2a07f4f6ea8349b09.png" sizes="96x96" />            
  <link rel="icon" type="image/png" href="https://d1b5oz78c0udqh.cloudfront.net/assets/favicon-16x16-ecb043d6bec4bf88aa1435bfa04000c2.png" sizes="16x16" />              

This should take the CDN for all static assets score from 90/100 to 100/100 on WebPageTest.