Learning Rails
Getting Your Local Environment Setup to Contribute to Rails
At RailsConf I’ll be leading a workshop on contributing to Ruby on Rails called “Breaking Down the Barrier: Demystifying Contributing to Rails”. My goal is to help you be confident in your ability to contribute to Rails. I’ll be focusing on contributing guidelines, advanced git commands, and traversing unfamiliar source code. I’ve allotted 90 minutes for the workshop so in order for you to get the most out of it you should have your system ready. In this post I’m going to go over the basics of getting set up.
Technically, the easiest way to get Rails running locally is to use the supplied VM. I prefer to have it running on my local machine, but if you’re using Windows I highly recommend using the VM. Although the VM is referred to the “easy way”, you likely already have 50% of the things you need installed on your system already if you’re actively developing Rails applications. If you do decide to use the VM you can skip these instructions. Please contact me on eileencodes to let me know if the VM directions are wrong. Or better yet, if you figure it out send a pull request!
Let’s get started with the basics of getting set up!
Ruby Manager
When working with Rails it’s likely you’ll be using a different Ruby version than you use in your production applications. It’s best to use Rails master with the most up-to-date version of Ruby. Currently, you can’t use Rails master / future Rails 5 without Ruby 2.2.2. You probably already have a way to have multiple rubies installed on your machine with either rbenv, rvm or chruby.
I personally use rbenv but I’ve used rvm in the past and hear good things about chruby. It really doesn’t matter which one you use as long as you can have multiple rubies installed on your machine.
Once you have that set up, install Ruby 2.2.1 2.2.2 (2.2.1 had a security vulnerability). Don’t forget if you have a new version of Ruby you’ll need to install bundler before you run bundle install on the Rails repo.
Fork & Clone Rails
Now we’ll get the Rails source code set up. First go to [github.com/rails/rails][rails-repo]{:target=”_blank”} and click “fork”. Some developers prefer to clone the main Rails repo and set up their fork as an upstream, but unless you have push rights to Rails (a commit bit) I don’t think this really makes sense. In my opinion having origin set as your repo works best so this guide is going to show you my preferred method.
Checkout your version of Rails to your local machine:
$ git clone git@github.com/your-fork/rails.git
You’ll need to get Rails master main repo as an upstream to your Rails. To do this simply run:
$ git remote add upstream https://github.com/rails/rails.git
Anytime you want to pull changes from Rails master into your master do:
Here you are pushing to your origin so your remote origin is always up-to-date with your master branch. Don’t work on your master branch and send PR’s from there. Always create a new branch. That way you can be working on multiple patches and your master is always clean and ready to checkout a new branch from. Pushing to your origin master also makes it easy to reset any of your branches to master without having to re-pull changes from upstream Rails.
Don’t forget to add a .ruby-version
file to your Rails repo, but be sure not to check this in. I have a .gitignore_global
file that sits in my home directory and ignores all .ruby-version
files. Then you should run bundle install
.
Databases
Ok now that you’ve got the Ruby and Rails source, you’ll need to get a few more things installed before you can start running Rails tests. And the most important of those things is databases!
It’s not really a requirement that you have ALL the databases installed but it’s a good idea to have the default databases that the Active Record supports; SQLite3, MySQL, and PostgreSQL. This will help you test the main adapters that are supported in Rails. It’s also a good idea if you’re working on any SQL specific parts of Active Record; you want to be sure you aren’t negatively changing the behavior of those other databases.
How you install databases is up to you. As a OS X user I install them with homebrew and follow the instructions output after installation. Remembering all the start/stop commands for databases is a pain though so I use LaunchRocket to control this. It’s a OS X preference pane to manage databases installed with homebrew. Additionally, you’ll need memcached for some ActionDispatch and ActionController tests.
Once you have the necessary databases installed you’ll need to create the databases and users required by the Rails tests.
MySQL
First create the users
Then create the databases
PostgreSQL
If you’re a Linux user create the user by running:
$ sudo -u postgres createuser --superuser $USER
If you’re an OS X user run:
$ createuser --superuser $USER
And then create the databases:
Creating and Destroying
It’s also possible to create both MySQL and PostgresSQL databases at the same time by running:
And you can destroy the databases and start over with:
Running the Tests
Now that you have Ruby, the Rails source code, and the databases installed it’s time to run the tests. Now don’t just run rake test in the Rails root directory because you will be there all day waiting for railties tests to finish. Simply cd into the library you want to test and run:
$ rake test
To run Active Record tests, be sure to include the database adapter you want to test or else sqlite3, mysql, mysql2, and postgresql adapter tests will all run. To run tests for specific adapters do the following:
And don’t forget all these commands are available if you run rake -T
in the directory you’re in.
See You at the Workshop
I’d tell you more about contributing to Rails but then I would have nothing to talk about at the workshop! I know it will be a lot of fun and you’ll learn tons. To read more about my workshop go to the RailsConf website.
If you have any issues at all getting set up ping me on twitter at eileencodes and I’ll do my best to point you in the right direction.
Nifty Methods: cycle(first_value, *values)
Recently I was working on an app and needed to "cycle" through some values. Previously, the code was using each_with_index
and using that index to figure out where the "odd" or "even" class was applied to the table rows. Since I needed to change the code to use map
I could no longer use each_with_index
effectively.
First my thinking was to use modulo to loop through and add the classes, but that seemed to be complete overkill for my situation.
I then turned to google to find something simpler. It seems Rails already has a dead simple solution. It amazes me every time I find something that I don't feel is necessary to write from scratch already in existence.
The method is cycle(first_value, *values)
. This can be used for many things, but the most obvious is cycling through "even" and "odd" classes, but can also be used to more advanced arrays. The Rails API uses cycling through colors as an example. The method also can accept a Hash to create a named cycle.
If you're interested in reading more about this nifty little method, you can find more details in the Rails API.
:has_many Relationships in ActiveAdmin
When I began using ActiveAdmin I discovered that there is not a lot of documentation on advanced usage such as displaying the :has_many relationships on the index and show page in the admin of the posts. I wanted to make it easy to add categories to posts and to know how posts were categorized easily.
Once the Category and Post models are created a join model also needs to exist, in this case Categorization. This part is the same as any other :has_many
, the hard part is display in the admin.
Go into the admin view for Post and add the following (other fields removed for easy viewing):
As you can see inside the tables creating a special inner table is required for best display. I add the link to the category edit in so it's easy to edit/view the category from the posts table.
To add checkboxes for category select it's as simple as adding f.input :categories, :as => :check_boxes
to your form view.
Want to figure out how to set up active admin? Read my "Lots of Love for ActiveAdmin" post. If you have questions, comment on the gist on github or find me on twitter.
ActiveAdmin is a really great simple way to implement an admin for a simple website or blog.
Honeypot for Rails Email Form
While working on my companies new website I realized that our contact form didn't have any spam protection and would become a favorite of bots not long after launch so I decided to add a honeypot.
If you're not familiar a honeypot is a hidden form that users can't see, but because bots don't read CSS they fill it in. If the form is filled in it automatically fails. This is a better alternative to the captcha because it doesn't require your users to type out a ridiculously illegible code (which from experience, i can tell you gets frustrating when you've gotten it wrong 60000 times).
I searched through a few gems and after being frustrated with the outcome decided to just do it myself because really it's just a few fields and the form is ajaxed and the gems would send a 200 response essentially removing the form, which was no my intention.
Open your form view and add a field for the honeypot. Be sure to add a label explaining it is a honeypot to ensure accessibility for screen readers and instructing users to not fill in the field.
Then go to your model and make your field accessible; attr_accessible :sweet_honey
One last quick step is to instruct your form what to do on save. You can have it simply fail with no error but that isn't accessible plus if anyone does fill it in, you might want to give a fun little message for them. I have my form rendering a partial because of the ajax-iness, plus I don't want the form to disappear just in case it's not a bot.
This is super simple implementation of a honeypot. I figured why make it more complicated when I just want to prevent send?
Lots of Love for ActiveAdmin
I have been so heavily immersed in work projects that I haven't had the time to write posts about rails - or do much of anything else.
Recently, I have been using the ActiveAdmin gem for the websites I've been building with rails. We are rebuilding our company website with rails and an ActiveAdmin backend. ActiveAdmin is awesome, the documentation could use a little love, but other than that I have no complaints about the system. I do believe everyone should build a rails administration system from scratch at least once to ensure understanding of how authentication works.
I'm going to go over some of the basics of getting up and running with ActiveAdmin and then in later posts will go into more detailed instructions on more complicated things you may want the admin to do like model relationships and integration with paperclip.
Installation
To get started add activeadmin
and meta_search
to your Gemfile
. Bundle install
and begin development! Activate the default admin user model by generating the resource: rails generate active_admin:resource AdminUser
. The default login information is admin@example.com/password.
Beginning Development
First, the admin user model must be configured. An important thing to note on installation is that all the fields for the user are visible including encrypted_password, reset_password_token, etc and if you try to update/add a user before changing the available fields you will get a "mass assignment" error. Find the admin_users.rb
in app > admin
and add the following:
You'll notice I've added extra fields to the db, namely a first_name and last_name to create full_name. This file changes the main views in the administration interface — the index view (table of users), the show view (each user's settings), and the form (updating/adding users to the admin panel).
Be sure to update your model to include validations, messages and relationships.
Adding new models is as simple as generating a model and a resource. If you want to create a model that isn't updated through the ActiveAdmin interface, create a has_many
join table model (ex, categorizations), but leave out the resource generation.
And that's all you need to get started, very simple gem to use. Although I could get a lot more in-depth about the features of ActiveAdmin I'm going to pause here. I encourage you to play around with it, the ease of use makes development even more fun. It's great to not have to worry about designing your admin interface for fast development.
Errors: Ruby 1.9.3 - uninitialized constant Capistrano (NameError)
Today I learned that order does matter in your Gemfile.
I got the error uninitialized constant Capistrano (NameError)
in the app I was developing when I tried to boot my local server. I had gem 'rvm-capistrano'
listed before gem 'capistrano'
- I guess when Rails tried to boot the app it read Capistrano from rvm-capistrano and assumed that Capistrano wasn't installed.
I intend to look deeper into this problem, but wanted to notfiy anyone who comes across the same issue.
I ended up solving this problem through Ruby Forum from someone with a very similar problem but slightly different solution.
Sorry for the Rough Travels
I am not entirely sure why yet but I have had a lot of trouble lately with this blog and it throwing 500 errors. I have been having a lot of troulble with MySQL - and at first I thought I fixed it and belive I made it worse. I have switched some stuff back and will hopefully soon figure out what the problem is and will be able to write a proper post about my troubles.
Airbrake a really nice app for this sort of thing because I don't need to read the logs to find out my site is trying to kill itself.
This is what is happening:
For awhile I was getting the following error:
ActiveRecord::StatementInvalid: Mysql::Error: MySQL server has gone away: SELECT `posts`.* FROM `posts` ORDER BY created_at DESC LIMIT 10 OFFSET 0
I added reconnect:true
to the database.yml because I figured that would fix it.
What happened instead is really weird and I can't figure out why the above change would cause this. The app started throwing a new error, more often. The error is sometimes on posts and sometimes on categories and differs depending on the page but generally looks like this:
ActiveRecord::StatementInvalid: Mysql::Error: : SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = ? LIMIT 1
What is weird is that's it's not getting the ID, but the page URL knows the ID, for example, when I click the category name with the ID 3, the slug is '/categories/3', but still throws the error on that page the mysql query is not getting the ID.
Maybe the answer is simple, but googling for the error doesn't result in much useful information. For now I've switched it back to the verison without the "reconnect:true" to see if the erros switch back again.
If you have any idea why this would be happening and would be interested in helping me out I'd really appreciate it. Find me on Github or Twitter.
Installing Airbrake for Your Rails App
What is Airbrake
In addition to New Relic I have also added Airbrake to my blog. Again, Airbrake is very simple to add add to any Rails App.
The Airbrake App tells you if any of your projects throw and error, and also notifies you which of your app environments did so. You have the option of the error notifying you via email, only receive emails for the production environment or to participate in Airbrake's beta program.
It also has Lighthouse & Github integration as well as tracking your deployments which is nice and convenient.
Installation and Use
Adding the Airbrake app is easy and I'll even go over an error and solution that occurred for me. First create an airbrake account and create your first project. When you create the project directions for adding Airbrake to your app will be visible.
Add airbrake to your Gemfile. I found this did not play nicely when I put the app in only my production environment.
gem 'airbrake'
Run bundle install
. Then run script/rails generate airbrake --api-key YOUR_API_KEY_HERE
. You can get your api key from that first screen when you create your first project. If this runs successfully you will see the airbrake test run in your terminal, followed by your configuration options which contain your api key, etc.
Now if you're using Capistrano you're probably wondering if there is anything special you need to do for your deploy. The good news is that Airbrake will add require 'airbrake/capistrano'
to your deploy.rb automatically. The bad news is that my capistrano script broke after the addition of airbrake. Previous apps we have Airbrake installed on run fine so I'm not sure if it's certain versions of gems, ruby or rails that throws the errors.
If you see an error that says `require': no such file to load -- rvm/capistrano (LoadError)"
then you probably have the same problem I have. After a little bit of research I found others had the same problem and reported that removing require './config/boot'
from the deploy.rb fixed the problem. Once I removed this it ran fine and airbrake noted my deploy. The problem I found is a know issue reported on github as Issue #26 - if you'd like to follow the progress of this error you can read up on it here.
Installing New Relic for Your Rails App
What is New Relic?
New Relic is a performance management system that our company just started using to monitor some of our larger apps. Since this app occasionally drops mysql connection (I'm thinking it's related to Unicorn) we're using it as a test case.
By using New Relic you can get real-time browser performance, app performance, database performance, email notifications. And on top of being a great resource it looks awesome. Some really nice design there.
Installation and Use
Installation for Rails Apps is easy. Add the gem to your Gemfile inside your production group.
gem 'newrelic_rpm'
When you're done with that add newrelic.yml
Inside your config/
folder inside your app. You can get the default settings from the github project.
You'll need a license key and to change your group's based on your configurations if you don't want the default options.
Once deployed New Relic automatically recognizes your Rails App and begins monitoring it. It monitors who is visiting your site and from what country as well as all the processes it is running. Definitely worth checking out.
Nifty Rails Methods: link_to_if, link_to_unless
I have for some time been wanting to make a "definitive list of awesome rails methods". There are so many great built in methods that I didn't realize existed when I was trying to build something from scratch. Sometimes it's annoying to find out that thing you're trying to build already exists - but if you haven't put 500 hours into it, it's usually a relief.
So today the featured definitve list of awesome rails methods are link_to_if
and link_to_unless
.
The nice thing about this method is it's great for changing links based on if a user is logged in, if the page is current, etc. Instead of writing an if else statement you can DRY it up by using link_to_if
or link_to_unless
. I found it fun to play around with and very useful as well. I personally used it for a complicated if else to mark a category for a prodcut as current. There is also an link_to_unless_current
which I didn't end up using because it wouldn't mark both the current category and parent category as active, link_to_if
worked much better for that.
Below is an example from the Rails API
More about these methods can be found on the Rails API.
Adding Additional Functionality to "Forgot your password?"
Recently I needed to add "forgot your password?" to a Rails app built by my company. I had never done this before so I watched the Remember Me & Reset Password Railscasts screencast. It was infinitely helpful, but I added a few things that were not in the video that I would like to share here. I followed the screencast for the most part: Adding a password_resets
controller, in addition to following the auth_token
directions. One thing I added was an intermittent page, instructing the user to check their email. I used the index.html.haml
layout for this. In addition I did not like it that users who hadn't requested a new password could access these pages, so I created a few redirects to prevent that. My index and new action show this redirect protection.
If a user attemps to go to the password_resets while already logged in they will be redirected to their profile, if they try to get there without being logged in they will be redirected to the login page, same with the new action.
I added the functionality to check whether the user's email was in the database and to return an error if it was invalid.
On the create action I have the page rendering the index instead of redirecting to maintain access to the email address so the view can display "An email has been sent to "insert email address". You must click the link in the email to reset your password."
Lastly, I wanted to make it more secure than the token expiring in 2 hours, so I added code that make the token expire if the user successfully changed their password. Once the user successfully changes their password reset_pass_token
will be erased from the database and will be redirected to their account profile, so they can edit other settings if they like otherwise, they recieve errors. If the new password save isn't successful within 2 hours the token will also expire.
The setup for "Forgot your password?" was rather easy and I learned a lot from implementing the functionality.
Functionality Recently Added to eileenbuildswithrails.com
I've been working on this blog in bits and pieces, when I have time. I've added some new functionality to bring it closer to a real blog CMS.
Adding Published at date changer
First I added a Published at date changer so that I could change my post dates if necessary. I think I'm going to do a "definitive list of RoR helper methods" because if it weren't for my pledge to watch all the railscasts videos in under a year I wouldn't have know about date_select
and datetime_select
and I would have been putting my head through a wall trying to figure it out. I feels almost like Rails cares about my sanity!
To use this helper method make :created_at
attr_accessible
in your Post model and then add the following to your admin view:
Belongs_to user for posts
I figured in the future I may have some guest bloggers, and it would be nice now to have all the posts have an owner so I woundn't need to go back and add it later.
First I created a migration so that would add the current users ID to the post table. Then I updated the post and user model adding belongs_to :user
to the post model and has_many :posts
to the user model.
Next, I wrote a method so I could call it in multiple actions if I needed to (for at least the first three posts I wanted to call the method on update to add the user to the table, also I only have one user so I knew nothing would happen).
In my view I was getting my most hated errror "You have a nil object when you didn't expect it". Yea Rails, if I expected it we wouldn't be haivng this conversation...
Anyway, I quickly figured it out was because I did not already have my author filled in so of course rails was complaining. Here is my view for the author section.
The Future
The next stesp will be adding the a lot more functionality and I will post on them as I do. I want to add:
- The ability for comments
- Ability to create draft, and future posts
- Contact Form
- Custom sidebar twitter feed
- Post tweets from admin for new post notification
- Login and profiles for guest bloggers
Functionality way further down that line but will be really awesome
- Front-end customization from admin area
- Creation and reorder for dynamic menus (think WordPress drag and drop menus)
- Ability to add and customize modules
- And much more...
Part 1: Launching Eileen Builds with Rails: Deployment with Capistrano, Unicorn, Nginx on Centos6
Note: I never did finish parts 2-4 for this blog post. I waited too long to write them and forgot how they worked. I've left this post up even though it's not really valid any longer. There are much better articles now on getting this running.
I'm going to do this post in four parts. Part 1: checklist things to do before deployment, Part 2 Capistrano, Part 3: Unicorn, and Part 4: Nginx. I also don't have the ability for draft posts set up yet, so...instead I'm publishing in parts so I don't need to write it all at once.
Launching this Rails app was not easy, although since I had never deployed an app, I wasn't expecting it to be easy. There are a bunch of little things you need to know about deployment if it's your first time that I think it would be helpful for other first-timers. Also, when you've been working on that web app for 24 hours straight you forget the all important mental checklist.
Please feel free to correct me to tell me I'm "doing it wrong" because this is my first deployment and I will fully admit I might have no idea what I'm doing.
Preparing Your App for Deployment
One thing I failed to do and I regret a lot is making sure certain files aren't include in git with my .gitignore
. Files to remove are:
- db/*sqlite3
- log/*.log
- public/assets* (now I did this because I wasn't using any public assets, and didn't want the rouge stylesheets being added)
- Gemfile.lock
Chances are if your app is running on sqlite3 in development it won't be in production and will more likely be using a MySQL database or PostgreSQL. My app is using MySQL so we'll go over setting up your Gemfile for that.
If you have just gem 'sqlite3' in your Gemfile you'll need to change it to what I have below. While here you'll probably want to add the gems needed for deployment as well.
Before deploying you'll need to precomile your assets with:
rake assets:precompile
This is really important because I forgot this step and could not figure out why my assets weren't showing up and I was getting a lot of "No Route Matches" in my logs. I didn't find this anywhere other were having this problem and no one said "hey maybe you forgot this really important thing."
Once capistrano is set up you can automate this task during deployment, but we'll cover that in Part 2.
When Parts 2-4 are written they will be linked to at the bottom of this post.
New Year, First Post
An Introduction
First, Happy New Year to everyone. This blog isn't a New Year's Resolution, so don't worry I won't write in it for 15 days and then never appear online again.
I started this blog for a couple reasons. I went to Big Nerd Ranch in September to learn the basics of Ruby and Ruby on Rails, and in that class we learned one of the ways we could contribute to the Rails community was writing a blog. I wanted a way to document and collect the things I learned, the mistakes I made, and also hope to help other beginners.
It will also help me hold myself accountable - to always be learning new things about Rails and giving back to the open source community.
From Photographer to Developer
When I thinking about how I got where I am now I can't help but laugh a little. I can tell you that if you asked me where I'd be now 5 years ago, I wouldn't have said where I am now. In high school, I focused a lot on art classes and thought perhaps I wanted to be an art educator and went to college believing that's what my major would be.
I think I was about 5 seconds into my freshman year when I realized teaching art was not something I wanted to do. I decided on a photography major and although I wish I had realized my passion for web development and computer science much earlier on I am grateful for all the creative energy I was required to use during my time as a photography major. I think I learned some valuable things that can easily be applied to where I am today, for example, the importance of maintaining the scope of a project.
In my senior year of college I took a Flash class for two reasons; it fit well in my schedule and I wanted to learn how to build a basic portfolio site for myself. As our final project I built my original website. At first my professor discouraged me from doing this because with only one month to complete the project he felt the timeline was a little to ambitious. I strive to constantly challenge myself. and I did in fact finish it ontime - with lots of hours over Thanksgiving break.
That was 3? 4? years ago I lose track. I took another class or two, but most of what I learned was on the job or things I taught myself. I have learned so much in a few years I cannot believe the information I absorbed.
For the last two and a half years I have been working for Evolving Media Network, a web development company in New York. Starting out with static html websites I quickly taught myself enough PHP to hack together WordPress sites and that was the majority of my responsibilities for a few years.
The Present
This past September I went to the Big Nerd Ranch in Atlanta to attend their Beginning Ruby and Ruby on Rails class. It was awesome and if you're thinking of going it's a great learning environment and the instructors are talented and helpful. Since then I have been practicing Rails by working on my own projects and have a few ideas for gems I hope to get to soon.
You can also follow me on twitter @eileencodes
Thanks for reading!