Preface

I'm trying to do some integrations with jruby and java. I encountered some problems, and found that there were only a few information about jruby. So I write down my experience and share it.

Install JRuby

Environment: Mac, rvm

rvm get head
rvm install jruby-9.0.4.0

in your project folder, run

rvm use jruby-9.0.4.0

or create a .ruby-version file

echo 'jruby-9.0.4.0' > .ruby-version

Calling Java

create a folder named getting-started-with-jruby, you can find the code in Github

quick start

create a Hello.java

public class Hello {
    public static void world(){
        System.out.println("Hello JRuby!");
    }
}

compile it with javac Hello.java

require 'java' will give you access to any bundled Java libraries (classes within your java class path)

then we create a calling-class-in-root.rb

require 'java'
Java::Hello.world()

run ruby calling-class-in-root.rb in termial, and you will see the output. Hello JRuby!

Read on →

install bash-completion

1
brew install git bash-completion

add bash-completion to your .bash_profile

1
2
3
if [ -f `brew --prefix`/etc/bash_completion ]; then
    . `brew --prefix`/etc/bash_completion
fi

show branch name

1
2
3
4
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u@\h \W\[\033[32m\]\$(parse_git_branch)\[\033[00m\] $ "

References

  1. https://github.com/bobthecow/git-flow-completion/wiki/Install-Bash-git-completion
  2. http://martinfitzpatrick.name/article/add-git-branch-name-to-terminal-prompt-mac

1. Quick Set

Can set pppoe usrname and pwd, enable DHCP. with 1WAN4LAN

set to 2WAN3LAN later, config interface in /ip address and interface in /ip dhcp-server

2. Interfaces

2WAN3LAN
/interface ethernet
set [ find default-name=ether1 ] name=ether1-gateway
set [ find default-name=ether2 ] name=ether2-gateway2
set [ find default-name=ether3 ] name=ether3-master-local
set [ find default-name=ether4 ] master-port=ether3-master-local name=\
    ether4-slave-local
set [ find default-name=ether5 ] master-port=ether3-master-local name=\
    ether5-slave-local
IP/Addresses
/ip address
add address=192.168.88.1/24 interface=ether3-master-local network=192.168.88.0

/ip pool
add name=dhcp ranges=192.168.88.100-192.168.88.254
Read on →

_.iteratee = function(value, context, argCount) {}

1
2
3
4
5
6
7
8
9
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
_.iteratee = function(value, context, argCount) {
  if (value == null) return _.identity;
  if (_.isFunction(value)) return createCallback(value, context, argCount);
  if (_.isObject(value)) return _.matches(value);
  return _.property(value);
};

_.iteratee的作用是生成callbacks,应用于collection的每个元素,返回分4种情况。

1) value == null

return _.identity

1
2
3
_.identity = function(value) {
  return value;
};

Example

1
2
3
4
> .identity('input value')
<- "input value"
> .iteratee(null)('input value')
<- "input value"

2) _.isFunction(value)

如果value为function, bind value(func) with context。 调用createCallback(value, context, argCount),return function(value, index, collection) {...}

3) _.isObject(value)

return _.matches(value) returns a predicate function.

4) else

return _.property(value)

Read on →

Yum Install PG9.4

1
2
3
4
5
wget http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-redhat94-9.4-1.noarch.rpm
yum instlal pgdg-redhat94-9.4-1.noarch.rpm
yum install postgresql94-server
service postgresql-9.4 initdb
chkconfig postgresql-9.4 on

Backup Data

1
2
su - postgres
pg_dumpall > dump.sql

Restore Data

1
2
3
4
service postgresql stop
service postgresql-9.4 start
su - postgres
psql < dump.sql

Config Network Access

vi /var/lib/pgsql/9.4/data/postgresql.conf

1
2
listen_addresses = '*'
port = 5432

/var/lib/pgsql/9.4/data/pg_hba.conf

1
2
3
4
5
6
7
8
# "local" is for Unix domain socket connections only
local   all         all                               ident
# IPv4 local connections:
host    all         all         127.0.0.1/32          ident
host    all         all         130.51.79.0/24        md5
host    all         all         10.210.29.0/24        md5
# IPv6 local connections:
host    all         all         ::1/128               ident

Remove PG8.4

1
2
yum remove postgresql
ln -s /usr/pgsql-9.4/bin/psql /usr/local/bin/psql

Refrences

  1. http://yum.postgresql.org/repopackages.php#pg94
  2. https://wiki.postgresql.org/wiki/YUM_Installation
  3. http://www.postgresql.org/docs/9.4/static/upgrading.html

1. Bundle a new gem

1
bundle gem jruby_gem

edit jrubygem.gemspec

1
2
3
4
Gem::Specification.new do |spec|
  ...
  spec.adddependency "jbundler"
end

Add TestUnit

1) edit jruby_gem.gemspec

1
2
3
4
Gem::Specification.new do |spec|
  ...
  spec.add_development_dependency "minitest"
end

2) edit RakeFile

Add test task code as below.

1
2
3
4
5
6
7
8
9
10
...
require 'rake/testtask'

Rake::TestTask.new do |t|
  t.libs << 'test'
  t.pattern = "test/*_test.rb"
end

desc "Run tests"
task :default => :test

3) create test/test_helper.rb

1
2
3
4
5
require 'jruby_gem'

require 'minitest/autorun'
require 'minitest/unit'
require 'minitest/pride'

Add Jar Dependency

edit jruby_gem.gemspec

1
2
3
4
Gem::Specification.new do |spec|
  ...
  spec.requirements << "jar 'jar-name', 'jar-version'"
end

Add Initializer

edit jrubygem/jrubygem.rb

2. In Rails App

edit Gemfile

1
gem 'jruby_gem', path: 'xxx'

1
2
3
touch Jarfile

jbunle

jbundle will read the requirements of jruby_gem.gemspec and then configure the classpath

Reference

  1. http://blakewilliams.me/blog/developing-gems-with-tdd-and-minitest-pt-1
  2. https://github.com/mkristian/jbundler/wiki/Gem-with-declared-jars
  3. https://github.com/richfisher/jruby_activiti

1. Issue of ruby class variables

1
2
3
4
5
6
7
8
9
class A
  @@var = 1
end

class B < A
  @@var = 2
end

A.class_variable_get('@@var')   # => 2

When you set a class variable, you set it for the superclass and all of the subclasses.

Read on →

1. About Monit

Monit is a small Open Source utility for managing and monitoring Unix systems. Monit conducts automatic maintenance and repair and can execute meaningful causal actions in error situations.

2. Install Monit

1
2
3
yum install monit
chkconfig monit on
service monit start

3. Configure Monit Web Server

/etc/monit.d/monitrc

1
2
set httpd port 2812
  allow localhost

4. Configurations

1
2
3
4
5
6
7
8
check process httpd
  with pidfile /etc/httpd/run/httpd.pid
  start program = "/etc/init.d/httpd start"
  stop program = "/etc/init.d/httpd stop"
  if failed host localhost port 8081
  protocol http then restart
  if totalmem > 1024 MB for 2 cycles then restart
  if 5 restarts within 5 cycles then timeout
1
2
3
4
5
6
check process sidekiq
  with pidfile /var/your_app/shared/tmp/pids/sidekiq.pid
  start program = "/bin/bash -l -c 'cd /var/your_app/current && bundle exec sidekiq --index 0 --pidfile /var/your_app/shared/tmp/pids/sidekiq.pid --environment production --logfile /var/your_app/shared/log/sidekiq.log --daemon'"
  stop program = "/bin/bash -l -c 'cd /var/your_app/current && bundle exec sidekiqctl stop /var/your_app/shared/tmp/pids/sidekiq.pid 10'"
  if totalmem is greater than 512 MB for 3 cycles then restart
  if 3 restarts within 5 cycles then timeout
1
2
3
4
5
6
check process mysqld
  with pidfile /var/run/mysqld/mysqld.pid
  start program = "/etc/init.d/mysqld start"
  stop program = "/etc/init.d/mysqld stop"
  if failed host 127.0.0.1 port 3306 then restart
  if 5 restarts within 5 cycles then timeout
1
2
3
4
5
6
check process redis
  with pidfile /var/run/redis/redis.pid
  start program = "/etc/init.d/redis start"
  stop program = "/etc/init.d/redis stop"
  if failed host 127.0.0.1 port 6379 then restart
  if 5 restarts within 5 cycles then timeout

5. Reference

http://mmonit.com/monit/

http://railscasts.com/episodes/375-monit

1. Start

Gemfile

1
gem 'capistrano', group: :development

1
bundle exec cap install

deploy.rb

1
2
3
4
5
6
7
8
9
10
11
set :scm, :git
set :repo_url, 'git_repo'
set :branch, 'develop'
set :repo_subdir, "your_subdir"
set :deploy_to, '/var/www/rails_apps/xxx'

after 'deploy:set_current_revision', :checkout_repo_subdir do
  on roles(:app) do
    execute "rm -rf /tmp/#{fetch(:repo_subdir)} && mv #{release_path}/#{fetch(:repo_subdir)}/ /tmp && rm -rf #{release_path}/* && mv /tmp/#{fetch(:repo_subdir)}/* #{release_path}"
  end
end

2. RVM

Gemfile

1
gem 'capistrano-rvm', group: :development

1
2
set :rvm_type, :auto
set :rvm_ruby_version, '2.0.0-p481'

3. Rails

Gemfile

1
2
3
4
group :development do
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
end

Capify

1
2
3
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

deploy.rb

1
2
3
4
5
6
7
set :linkeddirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}

set :keepreleases, 5

namespace :deploy do
  after :finishing, 'deploy:cleanup'
end

4. Whenever

Capify

1
require "whenever/capistrano"

If we set whenever_roles to [:db, :app] in deploy.rb, and have the following jobs in schedule.rb:

1
2
3
4
5
6
7
8
9
10
11
every :day, :at => '1:37pm', :roles => [:app] do
  rake 'app:task' # will only be added to crontabs of :app servers
end

every :hour, :roles => [:db] do
  rake 'db:task' # will only be added to crontabs of :db servers
end

every :day, :at => '12:02am' do
  command "run_this_everywhere" # will be deployed to :db and :app servers
end

Here are the basic rules:

If a server's role isn't listed in wheneverroles, it will never have jobs added to its crontab. If a server's role is listed in the wheneverroles, then it will have all jobs added to its crontab that either list that role in their :roles arg or that don't have a :roles arg. If a job has a :roles arg but that role isn't in the whenever_roles list, that job will not be deployed to any server.

5. Sidekiq

Gemfile

1
gem 'capistrano-sidekiq' , group: :development

Capify

1
require 'capistrano/sidekiq'

6. Go

1
cap production deploy

7. References

  1. https://github.com/capistrano/capistrano
  2. http://capistranorb.com/
  3. http://stackoverflow.com/questions/18838930/how-to-run-shell-commands-on-server-in-capistrano-v3
  4. https://github.com/javan/whenever

1. Get Start

1
gem install selenium-webdriver

2. Basics Usage

1
2
@driver=Selenium::WebDriver.for :firefox
@wait = Selenium::WebDriver::Wait.new(:timeout => 10)
Navigate
1
@driver.navigate.to 'http://xx.xx.xx.xx'
Switch
1
2
3
4
5
@driver.switch_to.default_content

@driver.switch_to.frame('frame_id')

@driver.switch_to.window('window_id')
Find element
1
2
3
4
5
@driver.find_element(id: 'xxx')
@driver.find_element(name: 'xxx')
@driver.find_element(tag_name: 'xxx')
@driver.find_element(xpath: 'xxx')
@driver.find_element(css: 'xxx')
Click
1
2
el = @driver.find_element()
el.click
Double Click
1
2
el = @driver.find_element()
@driver.action.double_click(el).perform

3. Input

Text
1
2
find_displayed_element(name: 'element_name').clear
find_displayed_element(name: 'element_name').send_keys('123')
Select
1
2
3
4
el = find_displayed_element(name: field_name)
el.find_elements(tag_name: 'option').each_with_index do |option, index|
  option.click if option.text == 'target_text'
end

4. Common functions

1
2
3
4
5
def find_displayed_element(option)
  @wait.until { @driver.find_element(option) }
  @wait.until { @driver.find_element(option).displayed? }
  @driver.find_element(option)
end
1
2
3
4
5
6
def switch_to_displayed_frame(frame_id)
  find_displayed_element(id: frame_id)
  @driver.switch_to.frame(frame_id)

  @driver.execute_script("window.showModalDialog = window.open;");
end
1
2
3
4
5
6
7
8
9
def get_window_id_by_title(window_title)
  @wait.until { @driver.window_handles.size > 1 }

  wnd_titl = @driver.window_handles.map do |w|
    @driver.switch_to.window(w)
    [w, @driver.title]
  end
  win_id = wnd_titl.find{|e1,e2| e2 == window_title }.first
end

5. References

  1. http://docs.seleniumhq.org/
  2. https://code.google.com/p/selenium/wiki/RubyBindings