Save your time in rails console by using irbrc to provide shortcuts for frequent commands

2015-08-13 22:10

正體中文版: 如何簡化「常常在 rails console 裡反覆輸入某些指令」的狀況

Finding your own user account in rails console is very frequent command in daily work. But key the full command is very inconvenient and waste time. You can use this technique to save time!

Solution

Edit ~/.irbrc (or ~/.pryrc if you are using pry)

class Dev
  def self.me
    User.find_by_email("your_mail@example.com")
  end
end

Then in rails console:

[1] pry(main)> user = Dev.me
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'your_mail@example.com' LIMIT 1
  ...

You can put most frequent used commands in there. But watch out for name collision.

p.s. I used to put a app/models/dev.rb in every projects. But it gets inconvenient when maintaining too many projects. Also your colleagues might have a different shortcut preferences. So I decided to put them in ~/.pryrc

Publish Jekyll to S3 and invalidate CloudFront cache automatically with Wercker

2015-02-27 14:00

I wrote a custom Wercker deploy step to invalidate CloudFront cache because it was not supported by the official s3sync step. But in Feb 24, 2015, wercker team has upgraded s3cmd to 1.5.1.2. Means that if you followed those tutorials to setup your Jekyll blog:

  1. Configure a Bucket for Website Hosting
  2. Simplify your Jekyll publishing process with wercker and Amazon S3
  3. Using CloudFront with Amazon S3

You can simply add this option and wercker will do the rest for you:

# in wercker.yml

deploy:
    steps:
        - s3sync:
            key_id: $KEY
            key_secret: $SECRET
            bucket_url: $URL
            source_dir: _site/
+           opts: --cf-invalidate

It will invalidate the path for default index (/subdir/). If you’d like to invalidate default index (/subdir/index.html) or both. Add applicable options:

  • --cf-invalidate-default-index: Will invalidate /subdir/index.html
  • --cf-no-invalidate-default-index-root: Will NOT invalidate /subdir/

Details are in s3cmd tool Usage.

Use codeclimate-test-reporter without a CI server

2014-11-15 13:29

For some reason, we didn’t setup a CI server. But we still want Code Climate to know test coverage after each deployment.

After some searching and experiment. We came up with this solution.

1. Add Capistrano run_tests task

Because we don’t have a CI server. We use Ben Dixon’s run_tests technique covered in his book Reliably Deploying Rails Applications, which is:

# lib/capistrano/tasks/run_tests.cap
namespace :deploy do
  desc "Runs test before deploying, can't deploy unless they pass"
  task :run_tests do
    test_log = "log/capistrano.test.log"
    tests = fetch(:tests)
    tests.each do |test|
      puts "--> Running tests: '#{test}', please wait ..."
      unless system "bundle exec rspec #{test} > #{test_log} 2>&1"
        puts "--> Tests: '#{test}' failed. Results in: #{test_log} and below:"
        system "cat #{test_log}"
        exit;
      end
      puts "--> '#{test}' passed"
    end
    puts "--> All tests passed"
    system "rm #{test_log}"
  end
end
# config/deploy.rb
set :tests, ["spec"]
before :deploy, "deploy:run_tests"

It will run test before every deploy. And stop deploy process if there are any failed test.

2. Install and setup codeclimate-test-reporter

Install codeclimate-test-reporter by adding it into Gemfile

# Gemfile
gem "codeclimate-test-reporter", group: :test

and run bundle install

Start the test reporter. Make sure that you put these lines at top of your spec_helper.rb.

# spec_helper.rb
require "codeclimate-test-reporter"
CodeClimate::TestReporter.start

Manually tirgger fist test report (your project token can be found at Settings > Test Coverage)

shell (in terminal) $ cd your_project_root $ CODECLIMATE_REPO_TOKEN=your_token_here bundle exec rspec spec

It should show following message:

Coverage = xx.xx%. Sending report to https://codeclimate.com for branch master... done.

Now you should be able to see the report showing in Code Climate. Sometimes it can take a few minutes.

3. Modify run_tests and make it report after each deployment

When you run rspec without CODECLIMATE_REPO_TOKEN, even you have test reporter started, it won’t send test report to Code Climate. In other words, you can control when to send report by giving token or not.

Modify the rspec command in lib/capistrano/tasks/run_tests.cap

I assume you always run complete test suit with this technique.

# lib/capistrano/tasks/run_tests.cap
namespace :deploy do
  desc "Runs test before deploying, can't deploy unless they pass"
  task :run_tests do
    test_log = "log/capistrano.test.log"
    tests = fetch(:tests)
    tests.each do |test|
      puts "--> Running tests: '#{test}', please wait ..."
+      rspec_command = "bundle exec rspec #{test} > #{test_log} 2>&1"
+      rspec_command = "CODECLIMATE_REPO_TOKEN=#{fetch(:codeclimate_token)} #{rspec_command}" if fetch(:codeclimate_token)
+      puts "--> Running tests: '#{rspec_command}', please wait ..."
+      unless system(rspec_command)
-      unless system "bundle exec rspec #{test} > #{test_log} 2>&1"
        puts "--> Tests: '#{test}' failed. Results in: #{test_log} and below:"
        system "cat #{test_log}"
        exit;
      end
      puts "--> '#{test}' passed"
    end
    puts "--> All tests passed"
    system "rm #{test_log}"
  end
end
# config/deploy.rb
set :codeclimate_token, your_token_here

Now, test will be run before every deployment and test report will be sent after that.

Note: you can put your token in run_tests.cap for simplicity. But I rarely commit any key or token into repostory. Instead, I put it in a git-ignored, separated config file. Than read and assign the value in config/deploy.rb.

Enable desktop notification for BitBucket HipChat hook

2014-04-15 13:42

Althought there is no checkbox for room notify. We can enable desktop notification by editing the API URL.

To enable desktop notification:

  1. Go to Admin (the Gear icon) > Hooks > HipChat > Edit
  2. Update API URL to https://api.hipchat.com/v1/rooms/message?notify=1
  3. Save

If you did not have a HipChat hook yet. Select HipChat from dropdown, hit Add hook and fill in RoomID and Token to add it.

The difference

https://api.hipchat.com/v1/rooms/message (Default) https://api.hipchat.com/v1/rooms/message?notify=1 (Enable desktop notification)

Inspired by this comment

Disable iTunes launching by 'Play' media key

2013-08-22 05:07

正體中文版: Mac多媒體快速鍵老是開啟iTunes,如何幹掉這個惱人的功能

By default, Mac always starts iTunes when you press Play media key on the keyboard even when VLC, Spotify, KKBox or Songbird player opened.

This can be annoying. This patch, authored by Farhan Ahmad, can remove the default behavior. And allows you to control the only opened player correctly.

cd ~/Documents/
git clone https://github.com/thebitguru/play-button-itunes-patch.git
cd play-button-itunes-patch
chmod u+x *
./Patch.command

And restart iTunes

Now, the media keys should not work for iTunes.

Run Patch.command again to re-enable.

Upgrade natescherer:apn_on_rails to new version of PRX:apn_on_rails gem

2013-07-11 21:33

正體中文版: natescherer:apn_on_rails 換到新版 PRX:apn_on_rails 筆記

Major changes

  • send_notifications method in PRX’s did not accept an array of notifications as paramter. It sends all unsent notifications.
  • Add APN::App. Put cert in database and allow you to send to multiple iOS apps with 1 rails app
  • Add APN::Group. Allow you to send group notifications. (But it still send one by one to Apple APN server)

Steps

#### Edit Gemfile

gem 'apn_on_rails'

And

bundle install

Migrateions

rails generate apn_on_rails:install
  • If it complains about some migrations have a same name, rename the old migrations and run again, delete the duplicated and rename back.
  • README says that maigration 002 create_apn_notifications was modified by hand and may cause a problem. See Upgrade Notes if needed.

And

rake db:migrate

Create first APN::App and move cert into database

Copy the content of /config/apple_push_notification_development.pem and apple_push_notification_production and save into APN::app#apn_dev_cert and APN::app#apn_prod_cert. See this post. (but you need to reslove the massive-assignment problem before running it on rails 3.2)

Modifiy APN::Notification.send_notifications and let it accept an array of notificaitons

Because that the natescherer:apn_on_rails folk accepts an array of notificaitons to send. But the PRX one are not. So I added it by hand.

Create config/initializers/apn_notification_reopen.rb

class APN::Notification

  # ...

  def self.send_notifications(notifications = APN::Notification.where("sent_at is null"))
    app_ids = notifications.map {|n| n.device.app_id }.uniq
    app_ids.each do |app_id|
      begin
        if (app = APN::App.where(:id => app_id).first)
          the_cert = Rails.env.production? ? app.apn_prod_cert : app.apn_dev_cert
          APN::Connection.open_for_delivery({:cert => the_cert}) do |conn, sock|
            unsent_notifications = notifications.select {|n| n.device.app_id == app_id }
            unsent_notifications.each do |noty|
              conn.write(noty.message_for_sending)
              noty.sent_at = Time.now
              noty.save
            end
          end
        end
      rescue Exception => e
        STDERR.puts e.message
        raise e
      end
    end

  end
end

Troubleshooting

#### NameError: uninitialized constant APN::App::RAILS_ENV

Add following line in config/environment.rb:

APN::App::RAILS_ENV = Rails.env

Errno::ENOENT: No such file or directory - /config/apple_push_notification_development.pem

run:

script/rails generate configatron:install

It will generate configatron files. Edit config/configatron/defaults.rb add:

configatron.apn.cert = ''
Site Search
Blog Archives