It’s been ages since I have posted anything. So busy with work. I just wrote this little snippet then and liked it. Was wondering if I could make it any shorter.
def shorten_tweet(tweet) tweet.length > 140 ? "#{tweet[0..136]}..." : tweet end
It’s been ages since I have posted anything. So busy with work. I just wrote this little snippet then and liked it. Was wondering if I could make it any shorter.
def shorten_tweet(tweet) tweet.length > 140 ? "#{tweet[0..136]}..." : tweet end
I love extending the ruby core! Makes code so neat and works so well with rails initializers. This method allows you to fetch the Acronym of an array of strings. It would be kinda cool to write something that works the other way taking a single string. Make using Faker… but I can’t think of any use. Then again IBM could not understand why people needed computers in their home so who knows. Anyway… it’s code time.
class Array def acronym result = "" self.each do |item| result << item[0] end result end end
Ahhh… its one of the moments in life that make you so happy your a ruby developer.
class Time def round(seconds = 60) Time.at((self.to_f / seconds).round * seconds) end def floor(seconds = 60) Time.at((self.to_f / seconds).floor * seconds) end def round_to_closest_hour if self.min > 30 self.round(1.hour) else self.floor(1.hour) end end end
Source:
http://stackoverflow.com/questions/449271/how-to-round-a-time-down-to-the-nearest-15-minutes-in-ruby
Time based web applications written in rails and javascript will sooner or later have to think about the following object life cycle.
1. Javascript Object
2. Request Params
3. Rails object
4. MySQL row
While rails has the last two covered and jQuery has mostly the second covered how do we get our data in to a form where this flow will be smooth. Javascript date objects don’t directly fit so I extended the date prototype to allow for this. This porototype mirrors the rails date time form helper and creates the correct data with the keys rails would expect to have.
Date.prototype.toRails = function(name) { var dateParams; dateParams = {}; dateParams[name + "(1i)"] = this.getFullYear(); dateParams[name + "(2i)"] = this.getMonth() + 1; dateParams[name + "(3i)"] = this.getDate(); dateParams[name + "(4i)"] = this.getHours(); dateParams[name + "(5i)"] = this.getMinutes(); return dateParams; }; //Use d = new Date(); date = d.toRails('start'); //now we can put this object on the server $.ajax ... data : date ...
As far as rails is concerned we might as well be using the datetime helper.
It seems that “rvm requirements” omits to mention the install of ncurses-devel when setting up for ruby installations with readline on Centos 5. Although you can install the readline package and and ruby its self with out getting an error there is a issue with the shared object. You will see this issue the first time you run irb. Ruby will complain that it can’t load readline. This took me the best part of two hours to figure out however it ended up being a missing package. Make sure you…
sudo yum -y install ncurses-devel
before you install ruby. Then you can install ruby compiling it with readline. HTH.
I have set-up a tutorial site for JavaScript with plans to add other languages. Its a getting started guide for any new programmers looking to start out with JavaScript development. If I get some positive feedback I will add more tutorials. To check them out head to Stewtorials
The other day I updated to Lion from Leopard. I know… I was keeping it real with an old OS but it got to the point where new apps where not working with leopard. While everything with the operating system update was fine there was a lot of time spent getting my ruby on rails install back up and running. One thing I did not understand is that I had made the leap to a 64bit system. This means a lot of recompiling as I hate package managers for osx.
First things first you will need to recompile MySQL from source. I am using 5.1. It seems to be the version of mysql that everyone is using. Some people might stick with sqlite however as I would never use it in production I would also never use it in development so I stick with MySQL. These commands are taken from Dan Benjamin’s hivelogic blog. Great work Dan! The link to the article is below in the sources section so if you run in to trouble check the article out.
cd /usr/local/src curl -O http://mysql.he.net/Downloads/MySQL-5.1/mysql-5.1.33.tar.gz tar xzvf mysql-5.1.33.tar.gz cd mysql-5.1.33 CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-shared --with-plugins=innobase make sudo make install
After these steps you should have the database recompiled for the new architecture of Lion. Great lets move on. Its worth noting that I am using RVM. The first thing I needed to do after the update is remove my existing version of ruby. This is the 32bit version and will not work.
rvm remove 1.9.2
With that done we need to reinstall ruby 1.9.2. We can use RVM to do this however there are a few things we need to update before this. Lets start with libxml. Download the latest version and compile it.
tar xzvf libxml2-2.7.3.tar.gz cd libxml2-2.7.3 ./configure --with-python=/System/Library/Frameworks/Python.framework/Versions/2.3/ make sudo make install
After this we need to install libxlst.
cd /usr/local/src curl -O ftp://xmlsoft.org/libxslt/libxslt-1.1.20.tar.gz cd libxslt-1.1.20 ./configure make sudo make install
All done now lets move on to readline.
At the time of this writing I was unable to install readline via rvm packages. There is a patch that fixes this however I am not sure its in head yet. The catch here is that in the current state when you install readline it will say that the install has been successful. This is not true. There is a topic on the RVM mailing list about this. For the moment I was able to get around this by compiling and installing readline myself. I have no doubt that this will be fixed soon but for the moment you will need to take this step. This last step is done assuming that you have readline 5.2 downloaded and untared. If you need help then I can add the download link.
export MACOSX_DEPLOYMENT_TARGET=10.7 export CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp" export CCFLAGS="-arch x86_64 -g -Os -pipe" export CXXFLAGS="-arch x86_64 -g -Os -pipe" export LDFLAGS="-arch x86_64 -bind_at_load" ./configure --prefix=/usr/local cd shlib sed -e 's/-dynamic/-dynamiclib/' Makefile > Makefile.good mv Makefile.good Makefile cd .. make && sudo make install
Next lets install zlib and iconv and openssh via RVM.
rvm pkg install zlib rvm pkg install iconv rvm pkg install openssl
Now we can install ruby 1.9.2. This will install the 64 bit version for us.
rvm install 1.9.2-head -C --enable-shared,--with-readline-dir=/usr/local --with-iconv-dir=$rvm_path/usr --with-zlib-dir=$rvm_path/usr --with-openssl-dir=$HOME/.rvm/usr,--build=x86_64-apple-darwin10
Once you have recompiled ruby you will need to create a new gem set. For me I have a gem set for each one of my projects so it was a matter of creating the gem set again and then running a bundle install.
http://www.markhneedham.com/blog/2010/07/08/installing-ruby-1-9-2-with-rvm-on-snow-leopard/
http://stackoverflow.com/questions/6317980/bundle-rake-error
http://exceptionz.wordpress.com/2010/02/03/how-to-fix-the-iconv-require-error-in-ruby-1-9/
http://groups.google.com/group/rubyversionmanager/browse_thread/thread/4130f40a654242a6?hl=en
http://techdebug.com/blog/2009/01/03/compiling-readline-on-an-osx-105-intel-x86_64
https://rvm.beginrescueend.com/packages/zlib/
http://nokogiri.org/tutorials/installing_nokogiri.html
http://hivelogic.com/articles/installing-mysql-on-mac-os-x/
I need to set up a billing system. I want to run you though how to set up such a system on a server complete with SSL and nginx as its a rails application we are deploying. I will be using a brand new install of Ubuntu however the ideas in this post should work with any server. First off lets set up our linux box
After you log in the first time you want to change your root password.
passwdThe system will prompt you to change the root password. Once you have done this then you can create a new user. You should NEVER log in with the root user.
adduser username
This command will prompt you to enter details about the user your creating however you only really need to enter the password. This is the user that we will use from this stage on so we need to add it to sudoers. If the user is not a sudoer then we cant install/compile anything. Nor can we make changes to system settings. Open the sudoers file with your favorite editor and add the following line
vim /etc/sudoers ## Add this line to the file username ALL=(ALL) ALL
Where username is the name of the user you have just created. Great now we have done this we have a user account and we don’t need to worry about our root user any more. Log out and then log back in with the new user. You should be able to run sudo commands.
First lets set up SSH Keys. This allows us to log in to our server with out having to enter a password. This is such a time saver and worth setting up. Any time we are doing a deployment using capistrano we are going to be glad to have our SSH key in place. First off if you don’t have it create a .ssh folder in your home directory(on your local machine – not on the server). Windows users… sorry your on your own here. You might have to read the PuTTY doc.
mkdir .sshAfter you have created the .ssh folder cd to it and run…
ssh-keygen -t rsa
This will create two files. One public and one private key. Never give out the private key. The public key can be given to anyone. In this case we are going to put the public key on our server. The public key is called id_rsa.pub.
scp ~/.ssh/id_rsa.pub username@serveraddress:
You will have to enter your password here. Once we have the key up there log back in to your server. You will still have to enter the password at this stage. You need to move the key file to a file called authorized_keys and set the ownership and permissions correctly on it.
mkdir .ssh mv id_rsa.pub .ssh/authorized_keys chown -R username:username .ssh/ chmod 700 .ssh/ chmod 600 .ssh/authorized_keys
Done! Logout and log back in. You should NOT be asked for a password. Once we have our keys set up there is one more thing that I would recommend doing at this stage. Changing the default SSH port. I always like to use the same port so set it to something that you will remember. Write it down because if you can not remember the port number you may be locked out of your system. To change the port we need to edit the ssh config file. Do so like this…
sudo vim /etc/ssh/sshd_config
The port setting should be on the first line. Chagne it save the file. The settings will not take effect until you restart ssh. At this point I would recommend you set up IP tables. While I am not going to talk about this in the first revision of this post I intend to add it later down the track when I have more time.
Now restart sshd
/etc/init.d/ssh reload
When you login you should use the new port. Remember that ssh keys do not have any port information so you will still need to tell ssh what port we want to use as its no longer set to default.
Once we have logged back in we need to install RVM. Ruby Version Manager is a great application that will help us manage ruby versions and gemsets. We can have many different gemsets and different versions of ruby. This allows us to serve applications from the same server in different ways.
First lets install some dependencies that RVM has.
sudo apt-get install git-core curl build-essential vim libcurl4-openssl-dev
Next we run the remote script that will install and setup rvm for us
su user$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
This script will use git to download RVM and install it. Note how we changed to the super user. This is because we want RVM multisite install. This is best for when we are installing RVM on servers.
type rvm | head -1
This should output the string “rvm is a function”. If so then we are in business and rvm has been installed.
We still have not installed ruby. Ruby its self has a number of dependencies. Lets install them first. The package names may differ from distro to distro so you might want to double check what all of them are. They should work for ubuntu though.
sudo apt-get install build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf
Currently we only have sqlite. If you want to use mysql run the following line.
sudo apt-get install mysql-server libmysqlclient-dev libmysql-ruby
Now lets use RVM to install some packages for ruby.
rvm pkg install zlib rvm pkg install openssl rvm pkg install readline
Now we can install ruby 1.9.2
rvm install 1.9.2 --with-zlib-dir=$rvm_path/usr --with-openssl-dir=$rvm_path/usr --with-readline-dir=$rvm_path/usr
Now we need to install bundler and passenger so we need to create a gem set. Gemsets are logical groups of gems. I normally go one gem set per application.
rvm gemset create application_name
Now install bundler. This is how rails will manage the gems it needs.
gem install bundlerOK now we have ruby installed lets install the passenger gem. This makes live so easy as it will configure and compile nginx for us.
gem install passengerOnce we have the gem installed we have access to some VERY helpful commands. passenger-install-nginx-module is the one we are going to run. This will install passenger for us and better yet it will go ahead and compile nginx for us too. All the time checking for any software that nginx might need. Very handy. I will not guide you though this process aside from running the command because the Phusion guys have created an amazing easy to use installer. To start the installer run
rvmsudo passenger-install-nginx-module
Once we are complete nginx will be installed with passenger and our webserver will be set up. Phusion even include the SSL module for Nginx which is great because we will need to use it for our credit card gateway. Incase you missed it nginx also gives you a configuration snippet. Incase you missed it here it is.
server { listen 80; server_name www.yourhost.com; root /somewhere/public; # <--- be sure to point to 'public'! passenger_enabled on; }
We will keep this handy as we will need it for our rails application when we set it up. Now we have everything installed we need to get a rails application on our server. I am going to assume you already have an application and that you are ready for deployment.
We will use capistrano to manage the deployment of the application. Lets log out of our server and go back to our application so we can install the capistrano gem locally. I will assume that your using RVM on your development machine and have not already got cap installed
gem install capistranoWith the gem installed lets “capify” our project. Make sure your in your current project directory and run the following command.
capify .
This should create a couple of files but the one we are interested in is deploy.rb. This file holds all of the details that cap needs to deploy the application to our server. It also gives us a place to write any extra tasks that might need to be performed on our application.
$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) require "rvm/capistrano" require "bundler/capistrano" set :rvm_ruby_string, '1.9.2@gemset' set :rvm_bin_path, "/usr/local/rvm/bin"
The above code tells cap what gem set we want or application to useon the server. It also tells cap that we are working with a single user install of RVM. Cap has a number of other details that need to be set for the deployment to work correctly. These include user names and server addresses. At this stage I like to add some tasks to my cap deploy file. These are…
namespace :db do desc "Create database yaml in shared path" task :default do db_config = ERB.new <<-EOF base: &base adapter: mysql username: username password: password development: database: #{application}_dev <<: *base test: database: #{application}_test <<: *base production: database: #{application}_production <<: *base EOF run "mkdir -p #{shared_path}/config" put db_config.result, "#{shared_path}/config/database.yml" end desc "Make symlink for database yaml" task :symlink do run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" end end namespace :rvm do desc "Create correct RVM file" task :create_rvmrc do run "cd #{current_path} && rvm use 1.9.2@#{application} --rvmrc --create" end end before "deploy:setup", :db after "deploy:update_code", "db:symlink" after "deploy:symlink", "rvm:create_rvmrc"
The above tasks manage our database configuration and create the correct RVM file. They are very handy as they completely automate the install on the server.
cap deploy:setup
This will login to the server and create all the folders. This is where our rails application will be set up on our server. Note how we don’t have to enter a password. SSH keys are great when dealing with cap because entering a password for each deployment gets old quickly.
cap deploy:check
Cap will go ahead and make sure your server has correct permissions to deploy your application. It will also check for any needed software such as source control managers. Once this is done and works then we are ready to deploy our application. Next lets deploy our application
cap deploy
This will install the application on the server in the deploy_to path. It will also create a number of symlinks. Its a great way of deploying an application because if something goes wrong it will roll back to the last version. Since this is the first time that we have deployed this does not apply to us. Now lets set up the database.yml file on our server. This is done with the “db” cap task.
cap db
Run another cap deploy after this and the database file will correctly link to the application. The next thing to do is create a database for the application and a database user. In the cap task make sure you replace username and password with the user account we are about to set up in mysql. Remember these can be any username and password you like. Just remember that the username and password in the database.yml file need to match what has been created in mysql. To create the user and pass in mysql do the following
CREATE DATABASE application_name_production; CREATE USER 'username'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON application_name_production.* TO 'username'@'localhost' WITH GRANT OPTION;
SSL uses private key authentication to verify that a site is who it claims to be. This is done by matching up keys. Much the same way as installing SSH keys works. To do this we generate our own private key. This is super secret! We do this on our server and it stays on the server. It is a security risk taking it off the server as you will have to transfer it over a network(this is unless you have physical access to your server). With this private key we create a certificate signing request. This CSR is then given to our SSL provider. Based on the CSR your SSL provider will create a certificate and send it back to you. They might do this via email as there is no risk if your certificate is out in the open. This certificate will only match the private key that we have on our server meaning that there is only one server that the certificate will match. Your SSL provider should have information available on how to prepare the certificate for use with Nginx as most people will most likely be running Apache(poor fools). One you have th crt file ready to go we point Nginx at that file and the private key we generated. The server will match the two up and users will be safe sending their credit card details via https.
Okay so we have everything installed. We have our application deployed. We have our application settings correct (we think… time will tell). The next thing to do is configure nginx to pick up on our rails application and work over SSL. Remember the code snippet we got when we installed nginx. Place that in your nginx config file with some changes. Here is the code snippet set up to work for SSL.
Open nginx.conf
vim /opt/nginx/conf/nginx.conf
Add our server configuration.
server { listen 443; server_name domain.com; root /where/your/app/is; passenger_enabled on; ssl on; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key; }
Note the ssl configuration is pointing at two files. A certificate and a key. For this setup we will generate the certificate and sign it our selves. This will NOT do in production as it will show users that the certificate is not trusted however for now its fine.
cd /path/to/ssl/certs openssl genrsa -des3 -out server.key 1024 openssl req -new -key server.key -out server.csr cp server.key server.key.org openssl rsa -in server.key.org -out server.key openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
OK now we have nginx all ready to go lets create our init script. The init script allows us to stop and start nginx when we need to and its not provided for us when we install nginx via passenger.
sudo vim /etc/init.d/nginx
Add the following to this file and save.
#! /bin/sh ### BEGIN INIT INFO # Provides: nginx # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the nginx web server # Description: starts nginx using start-stop-daemon ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/local/sbin/nginx NAME=nginx DESC=nginx test -x $DAEMON || exit 0 # Include nginx defaults if available if [ -f /etc/default/nginx ] ; then . /etc/default/nginx fi set -e case "$1" in start) echo -n "Starting $DESC: " start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \ --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; stop) echo -n "Stopping $DESC: " start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \ --exec $DAEMON echo "$NAME." ;; restart|force-reload) echo -n "Restarting $DESC: " start-stop-daemon --stop --quiet --pidfile \ /usr/local/nginx/logs/$NAME.pid --exec $DAEMON sleep 1 start-stop-daemon --start --quiet --pidfile \ /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; reload) echo -n "Reloading $DESC configuration: " start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \ --exec $DAEMON echo "$NAME." ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0
Now we have everything set up lets start nginx.
sudo /etc/init.d/nginx start
Once this is started point your browser to the correct domain via https and test your site out. Good luck!
http://articles.slicehost.com/2010/10/18/ubuntu-maverick-setup-part-1
http://articles.slicehost.com/2007/12/19/ubuntu-gutsy-nginx-ssl-and-vhosts
http://www.modrails.com/install.html
http://blog.bigrocksoftware.com/2011/01/07/rvm-nginx-passenger-rails-3/
https://rvm.beginrescueend.com/rvm/install/
http://excid3.com/blog/ruby-on-rails-3-and-mysql-on-ubuntu-10-10/
http://stackoverflow.com/questions/3644897/rvm-cannot-use-ruby-with-sudo
http://help.github.com/deploy-with-capistrano/
http://beginrescueend.com/integration/capistrano/
http://blog.ninjahideout.com/posts/a-guide-to-a-nginx-passenger-and-rvm-server
http://blog.ninjahideout.com/posts/the-path-to-better-rvm-and-passenger-integration
http://stackoverflow.com/questions/4349628/rails-3-app-deployment-bundler-rake-issues
http://wiki.nginx.org/HttpSslModule
23/08/2011 Added links to sources, added intro to ssl.
Sometimes an existing value in a HTML field can do so much for usability. The problem is these “existing values” can sometimes get in the way and make the page more difficult to use. Its fair to say that you want to clear that value when the user is ready to fill out the form. The focus event has you covered in this situation, but what about when the user does not enter any data after clicking on the form element? The element needs to perform some sort of persistence to reload the value that it was initialised with.
jQuery provides a great way to do this with the “data()” function. This function allows any data to be attached any DOM element. Very handy when you throw(excuse the pun) it in with a jQuery function. Here is my solution to reloading values for DOM form elements. Works best with type=”text”
jQuery.fn.contentOnBlur = function() { $(this).each(function(index, value){ $(value).data('initValue', $(value).val()); $(value).data('changed', false); }); $(this).focus(function(){ if(!$(this).data('changed')) { $(this).val(''); } }); $(this).change(function(){ $(this).data('changed', true); }); $(this).blur(function(){ if($(this).val() === '' && !$(this).data('changed')) { $(this).val($(this).data('initValue')); } }); }