Skip to content
Aug 24 11

RVM, Rake and Cron on Ubuntu

by admin

Tennnngh! I read countless blog posts, tried numerous approaches that I found and rebuilt the server more than a couple times. And finally I found what the missing piece was for getting a rake command to run in cron with rvm.

Most of the results I found (on stackoverflow) flagged the solution as adding the path to your rvm in your line item in crontab. Something like /home/username/.rvm/gems/rake my_awesome_task… etc. I tried every variation of that I could think of and got the same results.

I dont use cron every day so this was a revelation to me. I found out that you can set variables, environment variables in your crontab file.

So the solution was very simple. Edit the crontab like this.

  1. crontab -e

Then at the top of the file (mine is the first line)

  1. SHELL = /home/wylie/.rvm/bin/rvm-shell

Then my commands:

  1. * 4 * * * /bin/bash -l -c ‘cd /path/to/app && RAILS_ENV=production rake mytask –silent’

Done.

Hope that saves someone some time.

Aug 24 11

AWS Recipe

by admin

Seems Im not the only one who has had problems with ruby 1.9.2 and rvm on my Ubuntu servers. This recipe so far has worked great for every project running on it so far. Im not taking credit for all of it. Its a compilation of things that I have found on other blogs (too many to credit).

Use this AMI
ami-a403f7cd

Then add ssh, http and https to the default security group. Now you can shell in

  1. sudo apt-get update
  2. sudo apt-get build-essential
  3. sudo apt-get install curl git-core gitk git-gui
  4. sudo apt-get install libcurl4-openssl-dev
  5. sudo apt-get install vim
  6. sudo apt-get install rake
  7. sudo apt-get install apache2 apache2-mpm-prefork apache2-prefork-dev
  8. sudo apt-get install mysql-server mysql-client
  9. sudo apt-get install libmysql-ruby libmysqlclient-dev

Now for the RVM stuff

  1. sudo apt-get install ruby
  2. bash < <( curl https://rvm.beginrescueend.com/releases/rvm-install-head )

EDIT:: RVM has changed the install address. Check their website to get the latest bash install command

Open .bashrc and replace

  1. [ -z "$PS1" ] && return

with

  1. if [[ -n "$PS1" ]]; then

Then at the end of the file

  1. if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi
  2. fi

You should close the terminal and open a new one then enter

  1. rvm notes

You should see a bunch of options.

Now we need to add a bunch of stuff

  1. sudo aptitude install build-essential bison openssl libreadline5 libreadline-dev curl git-core zlib1g zlib1g-dev libssl-dev vim libsqlite3-0 libsqlite3-dev sqlite3 libreadline-dev libxml2-dev git-core subversion autoconf

Now we can run rvm list known and we should see a list of rubies

Time to upgrade our ruby

  1. rvm install 1.9.2-head
  2. rvm –default 1.9.2-head

EDIT:: RVM has changed a bit since I wrote this. Be sure to read their instructions to be familiar with the differences. Setting default has now changed to

  1. rvm use 1.9.2-head –default

Don’t forget the –default or your git hooks will never work

Lets get rails in there to test it out

  1. gem install rails

Try it out

  1. rails new testing

Should have created a new rails app.

Now we need to get our project from the git repo. But we need to give them a pub key

  1. cd ~/
  2. ssh-keygen -t rsa

(defaults, no passphrase)

  1. cat .ssh/id_rsa.pub

copy and paste that into the repo keys on your repo

Now set up the site

  1. cd /var
  2. sudo chgrp -R ubuntu www
  3. sudo chown -R ubuntu www
  4. cd www
  5. git clone [clone address] [dir name you want]
  6. cd [new dir name]
  7. bundle install

cool, now lets set up the webserver

  1. gem install passenger
  2. passenger-install-apache2-module

follow the instructions

Now we need to set up our git hooks for a heroku like deployment
shell into the server then cd to /var/www/[your app]/.git/hooks
copy the post-receive.sample to just post-receive
chmod it to 777
then edit it like so

  1. #!/bin/bash
  2. APP_PATH=/var/www/myapp
  3. # Production environment
  4. export RAILS_ENV="production"
  5. # This loads RVM into a shell session. Uncomment if you’re using RVM system wide.
  6. # [[ -s "/usr/local/lib/rvm" ]] && . "/usr/local/lib/rvm"
  7.  [[ -s "/home/ubuntu/.rvm/scripts/rvm" ]] && source "/home/ubuntu/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
  8.  
  9. echo "*******************************************"
  10. echo "    Deploying [APP NAME] to live server      "
  11. echo "*******************************************"
  12.  
  13. exit_with_error() {
  14.   echo "[DEPLOY] !!!!!!!!!!!!!!!!!!!! An error has occurred !!!!!!!!!!!!!!!!!!!!!!!"
  15.   exit 1
  16. }
  17.  
  18. cd ${APP_PATH}
  19. env -i git add .
  20. env -i git reset –hard || exit_with_error
  21. env -i git pull origin master
  22.  
  23. echo "[DEPLOY] –  * Running bundle"
  24. bundle install –deployment –without development test || exit_with_error
  25.  
  26. echo "[DEPLOY] –  * Migrating database"
  27. bundle exec rake db:migrate || exit_with_error
  28.  
  29.  
  30. echo "[DEPLOY] –  * Successfully deployed application to live server"
  31.  
  32. echo "[DEPLOY] – * Restarting application"
  33. mkdir -p tmp/
  34. touch tmp/restart.txt
  35.  
  36.  
  37. echo "*******************************************"
  38. echo "    Successfully deployed [APP NAME]       "
  39. echo "*******************************************"
  40.  

Then, in the .git/config file add this to stop all those pesky warnings

  1. [receive] denyCurrentBranch = false

Now we need to create a DB

  1. mysql -u root -p

create database [whatever you need here];

  1. exit

Lets add the new server as a remote for your git

  1. git remote add live ubuntu@[some ip]:/var/www/[app name]

I think were ready for a push. In your project update the config/database.yml and change the production creds to what you just created.
commit that change and push it to origin

  1. git push origin master

And now push it to live

  1. git push live master

tada.. git push deployment with gem updates and migrations

Just one thing left… database backups to S3. Thats for another post.

Feb 22 11

PayPal Recurring Payments with ActiveMerchant

by admin

I found several pieces to the puzzle but it took me a while to put it all together. After I got it working I thought I should write it down in case I needed to remember what I did or maybe someone else would find it useful.

The first thing you should know is that ActiveMerchant does not support recurring payments with PayPal. But Raymond Law generously made a fork that fixes this. I couldnt get the fix as a gem so I just installed it as a plug in. https://github.com/rayvinly/active_merchant/

Then I went to the Railscasts on PayPal with ActiveMerchant. http://railscasts.com/episodes/146-paypal-express-checkout

In my config/environments I made a slight change from the Railscasts example:

  1. config.after_initialize do
  2.   ActiveMerchant::Billing::Base.mode = :test
  3.   paypal_options = {
  4.     :login => "mysandboxlogingoeshere",
  5.     :password => "MYSANDBOXAPIPASSWORD",
  6.     :signature => "SANDBOXAPI"
  7.   }
  8.   ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
  9.   ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
  10. ::EXPRESS_RECURRING_GATEWAY = ActiveMerchant::Billing::PaypalExpressRecurringGateway.new(paypal_options)
  11. end

I made a registration controller:
rails g controller index new checkout complete

  1. def checkout
  2.      response = EXPRESS_RECURRING_GATEWAY.setup_agreement(:description => description, return_url => registration_complete_url, :cancel_return_url => registration_new_url)
  3.      
  4.       redirect_to EXPRESS_RECURRING_GATEWAY.redirect_url_for(response.token)
  5. end
  6.  
  7. def complete
  8.      token = params[:token]
  9.      response = EXPRESS_RECURRING_GATEWAY.create_profile(token, :description => description, :start_date => start_date, :frequency => frequency_in_months, :amount => amount_in_dollars, :auto_bill_outstanding => true)
  10.  
  11.      if response. success?
  12.           #handle success
  13.      else
  14.           #handle failure
  15.      end
  16. end

You can figure out your own way to handle the values and details of the transaction. The Date format can be set with

  1. start_date = Time.now

The amount can be just a number. Dont put it in quotes.

Oct 13 10

paginating multiple collections with will_paginate

by admin

Use case: I have a page with multiple post. Each post has multiple comments. I want to use the infinite_scroll jquery plugin to “paginate” through the comments and post.

Admittedly, nested pagination makes little sense until you think about it in context of having multiple infinite scrolls on a page.

Here are the bare bones.

My Post model:
def comment_pages(comment_page = 1)
self.comments.paginate( :page => comment_page, :per_page => 5 )
end

My View (haml version):
#comment_pagination= will_paginate(comments, :param_name => "comment_page_#{post.id}")

Now i have unique list that infinite scroll can use to paginate through.

Jul 2 10

Setting up a new dev environment

by admin

There are so many things i forget when setting up a new workstation. This time I took notes so I wont forget.

After installing VMWare fusion3 on my macbook pro I download the latest Ubuntu iso and start a new VM with it. I keep my work on TrueCrypt partitions. Then work my way down this list.

For starters

  1. sudo apt-get install git-core gitk git-gui
  2. sudo apt-get install subversion
  3. sudo apt-get install ssh-client
  4. sudo apt-get install ssh-server
  5. sudo apt-get install vim
  6. sudo apt-get install rake
  7. sudo apt-get install libxml2-dev

Then install sphinx
http://freelancing-god.github.com/ts/en/installing_sphinx.html
./configure, make, sudo make install

VMWare Tools
Turn off shared folders (i always get failures when i dont)
From the virtual machine menu, select install VMTools. Open the virtual DVD and put the zip file on the desktop and extract it there.
From a terminal cd Desktop/vmware…
Then sudo ./vmware-tools-install.pl
Enter key for all the defaults. Then run the networking stop and start commands at the end of the instructions.

Install Ruby

  1. sudo apt-get install ruby-full build-essential

or

  1. sudo aptitude install ruby build-essential libopenssl-ruby ruby1.8-dev

Install Apache

  1. sudo apt-get install apache2 apache2-mpm-prefork apache2-prefork-dev

Install Ruby Gems

  1. sudo apt-get install rubygems
  2. export PATH=/var/lib/gems/1.8/bin:$PATH

Install Rails

  1. sudo gem install rails

Install MySQL

  1. sudo apt-get install mysql-server mysql-client
  2. sudo apt-get install libmysql-ruby libmysqlclient-dev
  3. sudo gem install mysql

Install Passenger

  1. sudo gem install passenger
  2. sudo apt-get install apache2-threaded-dev libapr1-dev libaprutil1-dev
  3. sudo /var/lib/gems/1.8/bin/passenger-install-apache2-module

[follow passenger instructions]

VMWare Network connections
Since FF is the default browser you need to make a small change to browse the web.
Open FF and put about:config in the URL. Then filter for ipv6 and set false to true and restart FF. You should be online.

Shared Folders
Use TrueCrypt to keep your work on and share /Volumes/[your TC Drive] with VMWare. You will need to shift+apple+g to get the got to folder dialogue to find /Volumes.
You can access the files in your VM here
/mnt/hgfs

Install Gems
[what ever gems you need ]

Configure Apache
(Sill on your VM)

  1. mkdir ~/rails_development
  2. cd ~/rails_development
  3. ln -s /mnt/hgfs/[your drive]/myapp myapp

Now cd to /etc/apachec2/sites-available and sudo scp 000-default myapp
then sudo vim myapp

  1.  
  2. <VirtualHost *:80>
  3.      ServerName myapp.ubuntu
  4.      RailsEnv development
  5.      DocumentRoot /home/wylie/rails_development/myapp/public
  6.      <Directory /home/wylie/rails_development/myapp/public>
  7.           AllowOverride all              
  8.           Options -MultiViews
  9.      </Directory>
  10. </VirtualHost>
  11.  

Then cd ../sites-enabled
and sudo ln -s ../sites-available/myapp
then sudo rm 000-default
Finally restart apache

Set your hostfile
(Back on OS X)
get the IP in your VM and edit your hosts file on OS X
sudo vim /etc/hosts
[ip of VM] myapp.ubuntu
then run dscacheutil -flushcache (i usually have to run this a few times for it to take)

Install the DB
create any databases you need for your apps

Dont’ forget the memcached

  1. sudo apt-get install memcached
  2. sudo /etc/init.d/memcached restart

Fire it up
open your browser and go to myapp.ubuntu

Permission fixes
if you put id in the command line in your VM you will see that UID is 1000. The problem is that VMWare puts you in as UID 501 and GID 20. We need to update Ubuntu to match
sudo vim /etc/passwd
Then find your user and change 1000:1000 to 501:20, save and exit
You wont be able to make any more changes so you need to reboot. You cant log in either so you need to Ctrl + Alt + f1 to switch to terminal. Login there.
Then, you need to cd to /home and change the permissions on everything in your user dir like this
sudo chown -R 501:20 wylie
Then you need to update the group file sudo vim /etc/group
find dialup and change that to wylie [your username]. Then you need to find your username and change 1000 to 20.
sudo reboot, login and permissions are now fixed. Its a good idea to update your apache in /etc/apache2/envars. Change www-data to your username in both places

Git GUI fixes
The text in the UI is huge so you can open synaptic package manage and search for tcl. mark the 8.5 version for install. Then search for the tk8.5 and mark that for instalation. Then in command line
sudo update-alternatives –config wish
select the option with 8.5. It should be number 3.
Now when you open git gui it should look normal

Now get to work…

Jun 25 10

Regular Expression Tools

by admin

A friend shared a RegEx tool that came in really handy. Its www.rubular.com. I don’t get alot of opportunities to work with regex but when i do, having a new tool can make it almost fun.

I came up with this expression to match various URL’s that users enter that i could create new links from.

  1. (((https?):\/\/)?(([0-9a-zA-Z][-\w]*\.)+[a-zA-Z]{2,9}(:\d{1,4})?([-\w\/#~.?=&%@~])*))

Looks like cartoon swearing.

Mar 30 10

color scheme tool

by admin

How did I get this far without a tool like this?
A friend sent this link to me and I wanted to be sure that I never lost it.
http://colorschemedesigner.com/

Mar 2 10

jQuery Emoticon Selector Plugin

by admin

I couldn’t find an emoticon plugin for inserting an emoticon into a text area. I found plenty that converted the emoticon code into an image. So, I set out to write my first jQuery plugin.

If you choose to use this, keep in mind this was my first plugin and should be thoroughly tested before using it. And if you make it better I would very much like to see what changes you made.

Lets check it out.

The view has two components. The jQuery call and the div with the necessary elements. (my examples are how i used this in Ruby)

  1.  
  2. <% javascript_tag do %>
  3.   $(document).ready(function() {
  4.     $("div#emodiv").emoticate({icon: ’smiley-icon’, replacediv: ‘list’});
  5.   });
  6. <% end %>
  7.  

Then the div that you identified in the jQuery call.

  1.  
  2. <div id="emodiv">
  3.   <img src="/images/emoticons/emoticon-0100-smile.png" id="smiley-icon">
  4.   <div id="list"> </div>
  5.   <select name="emoticons">
  6.     <option value=":)">emoticon-0100-smile.png</option>
  7.     <option value="|-(">emoticon-0106-crying.png</option>
  8.     <option value=";)">emoticon-0105-wink.png</option>
  9.     <option value=":(">emoticon-0106-crying.png</option>
  10.     <option value="(pt)">279.png</option>
  11.     <option value="(ct)">104.png</option>
  12.     <option value="(au)">342.png</option>
  13.     <option value="(eg)">emoticon-0116-evilgrin.png</option>
  14.     <option value=":*">emoticon-0109-kiss.png</option>
  15.   </select>
  16. <div style="clear: both;"></div>
  17. <p>
  18.   <textarea id="comment_1"></textarea>
  19. </p>
  20. </div>
  21.  

What is going to happen is that the select and options will be changed to a UL list with the icon images. When an emoticon is clicked it will be inserted into the text area within the div. (The id for the textarea does need to be unique).

And here is the plugin.

  1.  
  2. (function($){
  3.  
  4.   $.fn.emoticate = function(options){
  5.  
  6.     var defaults = ({
  7.       replacediv:   ‘replaceme’,
  8.       image_path:   ‘/images/emoticons/’,
  9.       speed:        500,
  10.       icon:         ’smiley’
  11.     });
  12.     var options = $.extend(defaults, options);
  13.  
  14.     return this.each(function() {
  15.       var select = $(’select’, this);
  16.       var area = $(‘textarea’, this);
  17.       var icon = $("#" + defaults.icon, this);
  18.  
  19.       var emo =‘<div class="emoticon-box"><ul>’;
  20.       $(‘option’, select).each(function () {
  21.         var option    = $(this);
  22.         var emocode        = option.val();
  23.         var title    = option.text();
  24.         var link = $.fn.emoticate.emoticlick(title, emocode, defaults.image_path);
  25.  
  26.         emo += ‘<li>’
  27.             + link
  28.             + ‘</li>’;
  29.       }); //end option
  30.       emo += ‘</ul></div>’;
  31.  
  32.       select.remove(); //get rid of the select to make way for emotification
  33.       $("#" + defaults.replacediv, this).html(emo); //put the emotification HTML in the right div
  34.       $("#" + defaults.replacediv, this).hide(); //hide the emoticons
  35.      
  36.       var listdiv = $("#" + defaults.replacediv, this); //reset the var so it will work in the icon click.. this probably could be done better
  37.  
  38.       //bind the link for every a tag that is in the replaced div
  39.       $(‘a’, this).bind(‘click’, function() {
  40.         $.fn.emoticate.insertme(area.attr(‘id’), $(this).attr(‘id’));
  41.         return false;
  42.       }); //end bind
  43.  
  44.       //click the icon
  45.       $(icon, this).bind(‘click’, function (){
  46.         listdiv.show(defaults.speed);
  47.       });
  48.  
  49.       //function to click anywhere to hide the emoticons
  50.       $(document.body)click(function (){
  51.         listdiv.hide(defaults.speed);
  52.       });
  53.  
  54.  
  55.     }); //end select
  56.  
  57.   }; //end function
  58.  
  59.  
  60.   $.fn.emoticate.emoticlick = function(id,emocode, image_path){
  61.     return ‘<a href="#" id="’ + emocode +‘"><img src="’ + image_path + id + ‘"></a>’;
  62.   };
  63.  
  64.   $.fn.emoticate.insertme = function(areaId,text){
  65.     var txtarea = document.getElementById(areaId);
  66.     var scrollPos = txtarea.scrollTop;
  67.     var strPos = 0;
  68.     var br = ((txtarea.selectionStart || txtarea.selectionStart == ‘0′) ?
  69.     "ff" : (document.selection ? "ie" : false ) );
  70.       if (br == "ie") {
  71.       txtarea.focus(); var range = document.selection.createRange(); range.moveStart (‘character’, -txtarea.value.length);
  72.       strPos = range.text.length;
  73.     }
  74.     else if (br == "ff") strPos = txtarea.selectionStart;
  75.  
  76.     var front = (txtarea.value).substring(0,strPos);  
  77.     var back = (txtarea.value).substring(strPos,txtarea.value.length);
  78.     txtarea.value=front+text+back;
  79.     strPos = strPos + text.length;
  80.       if (br == "ie") {
  81.       txtarea.focus();
  82.       var range = document.selection.createRange();
  83.       range.moveStart (‘character’, -txtarea.value.length);
  84.       range.moveStart (‘character’, strPos);
  85.       range.moveEnd (‘character’, 0);
  86.       range.select();
  87.     }
  88.     else if (br == "ff") {
  89.       txtarea.selectionStart = strPos;
  90.       txtarea.selectionEnd = strPos;
  91.       txtarea.focus();
  92.     }
  93.     txtarea.scrollTop = scrollPos;
  94.   };
  95.  
  96. })(jQuery);
  97.  

Or you can download it here.

Dec 20 09

Installing passenger on ubuntu has some issues

by admin

I followed the instructions on the Ubuntu site and the modrails site and everything would install fine but I could never get passenger to serve pages to apache.

Passenger assumes the permissions of the default apache user. And if you don’t set up your default user as www-data when you install Ubuntu Passenger wont have permission to run the app.

Open up /etc/apache2/envvars and change the www-data user and group to match your default user and group and you should be set.

Oct 30 09

Watch the whitespace

by admin

I have been spending the last hour wondering why this doesnt work.

Post.find_by_sql["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]

Its because it needed to be like this:
Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]

yeah, you need that whitespace there.