Use accept_alert to get the alert message.

  • Poltergeist ignores alerts/confirms by default(source)
  • Poltergeist has had support for Capybaras modal api since September 2015( source)

That means you can same syntax for Poltergeist or capybara-webkit.

expect(accept_alert).to eq("Javascript alert message")

# or with block syntax

# will fail if alert message doesn't match
accept_alert("Javascript alert message") do 
  # next expectation
end

The first one expect(accept_alert).to reads a bit weird, but that's the return value of accept_alert.

June 6, 2016 #css

If you’re not happy with the default text-decoration: underline, want to tweak the thickness of the underline or vertical space between the text and the underline, then you may want to the background trick introduced in this post. Medium is also using this kind of technique.

// use background image to draw the underline
// this way we can tweak the vertical space between text and underline
a {
  text-decoration: none;

  background-image: linear-gradient(to bottom, rgba(0,0,0,0) 50%, rgba(0,0,0,.6) 50%);
  background-repeat: repeat-x;
  background-size: 2x 2x;
  background-position: 0 22px;
}

A quick demo of how it looks like:

text underline with background image demo

One caveat of this approach is, the position and thickness of the underline is depending on the font size. So if you’re using a different font-size as I do in the demo, you may need to change the background-position to fit your design.

Also if you want to apply it to different part of your page which all have different font-size, you will need to figure out the exact size for each part.

In my blog I’m using SCSS variables to document this behavior.

$post-font-size: 20px;
$underline-size: 2px;

background-size: $underline-size $underline-size;
background-position: 0 ($post-font-size + $underline-size);
June 6, 2016 #testing

When debugging if you want to check at some lines where you forget to put the binding.pry, you could use some help from pry-byebug's break points feature.

You can set and adjust breakpoints directly from a Pry session using the break command:
https://github.com/deivid-rodriguez/pry-byebug#breakpoints

break SomeClass#run            # Break at the start of `SomeClass#run`.
break app/models/user.rb:15    # Break at line 15 in user.rb.
...

Please bear with me with this example as a showcase.

scenario "Guest can't view draft post" do
  post = create(:post, title: 'Vim', published_at: nil)
  binding.pry
  visit post_path(post)
  expect(page).not_to have_content('Vim')
end

Suppose you put the first binding.pry there to check the creation of post, then somehow you also want to check what's going on in the controller, normally you would stop/finish the spec and drop the binding.pry to controller and rerun the spec. With pry-byebug you could set the breakpoint in the runtime: when the execution is stopped before the visit post_path(post)

[1] pry(#<RSpec::ExampleGroups::Posts>)> break PostsController#show

  Breakpoint 1: PostsController#show (Enabled)

  10: def show
  11: end

Now the breakpoint is set, if you continue the spec then it'll stop at the posts#show action.

This is also very useful when you check some codebase you're not familiar with like gems, during the debugging you also want to check some local variables inside a block or so, with the break command now you don't need to make changes to the library and restart your rails server.

June 5, 2016 #rspec #poltergeist

The default window size for poltergeist is 1024 x 768, in some cases you may want to change it to fit your specs.

Change Window Size Per Spec

page.driver.resize_window 1200, 768

Then you can check it this way.

page.driver.browser.client.window_size # => [1200, 768]

Note that this will not change the default window size for other specs, so no need to resize it back.

Change Window Size Globally

If you're using RSpec, you may want to create a metadata tag for it.

RSpec.configure do |config|
  config.before(:example, :mobile, type: :feature) do
    page.driver.add_headers("User-Agent" => "iPhone")
    page.driver.resize_window 320, 568
  end
end

Here we registered a :mobile metadata tag to change the window size to 320, 568, also set the user agent to further simulate the request from a mobile.

scenario "Do something in mobile", :js, :mobile do
  page.driver.browser.client.window_size # => [320, 568]
end

Change Default Window Size

You could also customize the window size when register the poltergeist drive.

# spec/support/capybara.rb
require 'capybara/poltergeist'

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, window_size: [1600, 768])
end
Capybara.javascript_driver = :poltergeist
May 28, 2016 #ruby

Ruby Module is an easy and great way to encapsulate related methods/constants and extend a class, but sometimes I find myself really want to tell it something about the current class.

A pseudo code of my "wish" looks like this: of course it's invalid, Ruby doesn’t allow us to do so.

class Post < ApplicationRecord
  include Publishable(column_name: :published_at)
end

Recently I read a blog post about how the author learned from reading some ruby gems' implementation to allow including a module with argument. Sounds fun so I gave it a try.

When you may want to include a module with arguments?

Let's first see an example, this may not be practical but at the moment I couldn't think of other great ones so please bear with me.

module Publishable
  def publish
    update(published_at: Time.now)
  end
end

class Post < ApplicationRecord
  include Publishable
end

There's nothing wrong with this code but some may argue that the Publishable module depends on the published_at column name, if someone renames the column to published_on then it'll be broken, it's coupled to the Post class.

One way to solve it may look like this:

module Publishable
  def publish
    update(publishable_column_name => Time.now)
  end

  private

  def publishable_column_name
    raise NotImplementedError
  end
end

class Post < ApplicationRecord
  include Publishable

  private

  def publishable_column_name
    :published_at
  end
end

Now the Publishable is relying on its "host"(Post) to define the method publishable_column_name to explicitly tell it the column name, otherwise it will raise the not implemented error. But the downside is the module's requirement leaks to Post, and that's arguably break the purpose to use a module, which is to group all methods of a concept in one place.

I'm thinking this could be a use case for the technique I'm gonna show you in this blog post.

Trick: A Class Inherits From Module

How the trick work is already introduced in the article above, let's fast forward to the end result now.

class Publishable < Module
  def initialize(column_name)
    @column_name = column_name
  end

  def included(base)
    column_name = @column_name

    base.class_eval do # self is Post class
      define_method(:publish) do  
        update(column_name => Time.now) # self is Post object
      end
    end
  end
end

class Post < ApplicationRecord
  include Publishable.new(:published_at)
end

The notable things are

  • class Publishable < Module, we're not declaring a module, instead we're making a class that inherits from module
  • When we include this module, we can now initialize it with any arguments
  • The arguments will be available inside the Publishable "module", hence no the knowledge is decoupled
  • Use define_method(:publish) { } instead of def publish, latter will make you lose the context and you can't access column_name variable anymore

Why It Works?

I'm gonna borrow the code from the article, this is how Rubinius handles module and is identical to MRI Ruby:

def include?(mod)
  if !mod.kind_of?(Module) or mod.kind_of?(Class)
    raise TypeError, "wrong argument type #{mod.class} (expected Module)"
  end
  # snip
end

When we do include SomeModule, this code will be executed to check if the target is a valid module. The trick is how we could manage to pass that check, that is "something is kind of Module and not kind of Class".

class Publishable < Module
end

Publishable.kind_of?(Module) # => true
Publishable.kind_of?(Class) # => true

Publishable.new(:published_at).kind_of?(Module) # => true
Publishable.new(:published_at).kind_of?(Class) # => false

With this trick you can pass whatever dependencies from the host to the module. Hope you find it useful, and let me know if you find a good use case with it in real world 😁Not sure if it's yet another case of abusing Ruby's flexibility to driver it too far, I do concern about its possible confusion when bring to teams in which people are most likely not aware of this kind of hack.

Further Reading

These 2 gems are using the same technique, and their full implementations are really easy to read and follow.

May 15, 2016 #rails

Just updated this blog to Rails 5.0.0.rc1 from 4.2, since this is a pretty small hobby blog app the update was quite simple and smooth.

1) Update your Gemfile, then bundle update rails

# core part of rails 5
gem 'rails', '~> 5.0.0.rc1'
gem 'turbolinks', '~> 5.x'

# use the same web server
gem 'puma', '~> 3.0'

# use latest master branch to make bundle resolve dependencies
gem 'kaminari', github: 'amatsuda/kaminari'
gem 'simple_form', github: 'plataformatec/simple_form'
gem 'rspec-rails', github: 'rspec/rspec-rails', tag: 'v3.5.0.beta3'

# Fix for https://github.com/jnicklas/capybara/issues/1592
gem 'capybara', github: 'jnicklas/capybara'

2) rails app:update to update the configuration files(config/*, bin/*)

Use d to check the diff and y to overwrite if it's ok.

3) Create app/models/application_record.rb like this

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

4) Update for turbolinks

This is equal to bind on window.onload, DOMContentLoaded, or jQuery ready events

$(document).on "turbolinks:load", ->

Also check the official guide on upgrade your rails app

May 12, 2016 #ruby #regex

If the task could be achieved by sprinkling some ruby magic, then better do it rather than trying to find the perfect reg expression.

One day I was trying to convert a liquid img tag to markdown style, one tricky part is the image caption can be omitted.

img_1 = "{% img http//example.com/image.jpg %}"
img_2 = "{% img http//example.com/photo.jpg Image Caption %}"

regex = /{% img (\S+) (.*)\s?%}/

img_1.match(regex)
#<MatchData "{% img http//example.com/image.jpg %}" 1:"http//example.com/image.jpg" 2:"">

img_2.match(regex)
#<MatchData "{% img http//example.com/photo.jpg Image Caption %}" 1:"http//example.com/photo.jpg" 2:"Image Caption ">

The caption matched for img_2 contained a trailing space: Image Caption . I was trying to tweak the regex to eliminate the trailing space but my limited knowledge couldn't get me there.

This is a good place to use gsub with a block, so I could further borrow the String#strip power to get rid of the trailing space.

def convert_liquid_img_tag_to_markdown(text)
  text.gsub(/{% img (\S+) (.*)\s*%}/) do |liquid_img_tag|
    url = Regexp.last_match[1] # same as \1 for inline style
    caption = Regexp.last_match[2].strip

    "![#{caption.to_s.strip}](#{url})"
  end
end

convert_liquid_img_tag_to_markdown(img_1)
# => ![](http//example.com/image.jpg)
convert_liquid_img_tag_to_markdown(img_2)
# => ![Image Caption](http//example.com/photo.jpg)

The link above from thoughtbot mentioned the meaning of having an intention-revealing name, liquid_img_tag in this case, but what's more powerful is the inside the block it's all ruby and matched strings, you can do whatever you want with it.

I'm still curious about the right regex to get rid of the trailing space, but for a simple, one-off task it saves a lot of time to ulitize the ruby power inside the gsub block.

Another example is logging the before/after:

def convert_liquid_github_tag(text)
  return unless text

  text.gsub(/{% gist (.+) %}/) do |match|
    html = "<script src=\"https://gist.github.com/kinopyo/#{Regexp.last_match[1]}.js\"></script>"

    puts "#{match} to #{html}"
    html
  end
end
May 6, 2016 #book

Have you ever felt this way? “This is a great book but I only wish it could be shorter”.

thick book

I’ve never finished Getting Things Done, the famous personal productivity and task management book. Even though I love the idea and concept, there’re way more words seemingly unrelated or off topic. Don’t feel motivated enough to continue, that’s why I dropped out.

Continue reading…

Another one is the 7 Habits of Highly Effective People, part of me still feel ashamed not finishing this book but same reason above, too redundant.

Not All of Us Want Quick-fix But…

It’s not like all of us want a bullet points or checklists to quick fix whatever problems in our life. We pick up the book instead of just googling “how to blah blah blah” right?

So I really hope there is a good balance point once the story is well told, conclusion is laid out, then that’s it, no more off topic contents to make an already great work less great.

Books That Are Short Yet Great

Among all the books I’ve read, REMOTE is outstanding because of its contents and its length. Precise, concise and convincing. I remember the author mentioned that after they wrote the whole book, they cut it to half size to save readers’ time.

The free ebook “SHAVE 10 HOURS OFF YOUR WORKWEEK” by Michael Hyatt is another great example, only 50 pages but it perfectly covers all the points.

And one timely tweet I saw recently is this: “21 minutes edited down to 14 minutes (- 33%) because I respect your time.”

Isn’t this another great aspect of delivering your contents that most book authors are either ignoring or being kept in blindspot? You don’t need to pack tons of words to make it a book, while you can write a blog post.

April 27, 2016 #turbolinks #adsense #dfp

Turbolinks Compatibility with DoubleClick for Publishers has already provided great solution to let Turbolinks compatible with DoubleClick for Publishers(DFP), but unfortunately just copy and paste the code didn't work for me, I need to make some modifications to the original code.

Continue reading...

According to the same site, you can no longer use Google Adsense with Turbolinks so you have to use the DFP.

Google has cancelled AJAX support for AdSense, so this solution no longer works. Your best course of action is to use DoubleClick for Publishers.

I'll provide the whole snippets all involved later, here are the changes you need to make in addition to the code snippet.

  1. Change the markup where you want to display the ads from data-gpt-div-id="div-gpt-ad-123456789-0" to id="div-gpt-ad-123456789-0"
  2. Change the javascript code from divId = $slot.data('gpt-div-id') to divId = $slot.attr('id')

Make sure you disabled your browser AdBlock extension, or whitelist your domain(both local and production) to be able to see the ads. Open browser in incognito mode also works.

Here is all the code for it.

April 25, 2016 #apple pencil #writing

Paradigm Shift in Writing and Notes Taking

1 Week after using Apple Pencil with iPad Pro 9.7'

I’d never had any expectations on “writing with a pen” on an iPad or any electronic device, to be honest. In the past I’ve tried some pens in the market but was never convinced. This Apple Pencil though, “it really could be a game changer”, said by my several friends and multiple sources, and now I truly believe it and its potential.

Continue reading…

iPad Pro 9.7 vs iPad Air 2

After the new 9.7 inch iPad Pro was released last month, I did lots of research on the typical subject: “should I buy it?”

I was struggling between the new Pro and iPad Air 2, the two has exactly the same size, and since I’m not a “power user”: not a designer nor musician, the improved performance wouldn’t help me that much as I often just use this device to read books and net surfing. I almost made my mind to go with Air 2 until I tried the Apple Pencil on my friend’s Pro. The experience was way better than I expected, so I decided to give it a shot, and so far I’m pretty happy about it.

Changes in Writing Style

I’ve written 3 blog posts on the iPad Pro, I’m using the app GoodNotes, which could convert your writings to “e-text”.

It feels much more natural to write with a pen, I mean the Apple Pencil, than staring with a blank screen with a constant blink cursor. And also no need to worry about finding the right link/image or wasting time on trivial editing.

Now my writing flow is

  1. Write first draft on iPad Pro with the Apple Pencil + GoodNotes
  2. Export it to Apple Notes
  3. Edit and publish on laptop

Writing More

I’m writing more. Besides blog posts, I’ve also switched my journals, work notes, daily simple notes and weekly review to this new writing style.

It has the same feeling of writing on a real paper, and also combines the functionalities of the e-notes: accessibility, search ability, portability, rich format.

Indeed the Apple Pencil is really a game changer to me. It’s so good and so intuitive to transfer your thoughts into words. When it comes to writing I don’t think I’ll need the Smart Cover with keyboard.

I’m enjoying this writing style. If you’re interested, try the Apple Pencil first to see if it is the thing for you.

p.s. Here is the screenshot of the draft of this post when it was first written on the iPad Pro, I know my handwriting is terrible :) but at least it motivates me to get things done and dump thoughts into words. 😁