Red-green-refactor is an important concept in TDD when you are using tests to drive your code and I'll use an example to demonstrate how this works. First I start off with a series of descriptions about what I want my code to do. As an example, I have a todo list that has a name and description and I want to write a method that checks if my object only has a name defined. So my initial test setup would be:
describe :name_only do
it "returns true if the description is nil"
it "returns true if the description is an empty string"
it returns false if the description is a non empty string"
end
GitHub Flow is a workflow guideline for how to work with GitHub and revolves around the idea of deploying regularly to GitHub. This ensures that it is very difficult, if not impossible, to introduce a large number of significant bugs. Additionally it enables me to quickly address issues of all kinds.
When talking about testing there are three main techniques to talk about:
Unit tests: models, views, helpers, routes
Functional tests: controller
Integration tests: emulate the end user
You'll hear it lots, fat models/skinny controllers but I was working on a project recently where my controller code was putting on a bit of weight!
The requirement was that when a post was saved with a url, a gem I had installed called LinkThumbnailer would visit that url to find the first image on the page and return the image url.
Building my own application from scratch has been an amazing experience and there's no way I'd have progressed this fast without the guys from Tealeaf Academy and a local developer I've been working with.
First a quick bit of info on my application. I wanted to create an application that could be used by healthcare professionals to share blog articles about treatment techniques. The intention is for bringing about better patient care in the long run by providing easy access to information without having to trawl through a lot of sites and missing out on information. In the long run I want to add functionality for users to write CPD articles based on the blog posts which can be presented to their professional body. For now though the functionality is quite similar to the PostIt! application I built in the tutorials, although I have added quite a few extras to make it interesting.
You can find my application here: CPD Boost and code: GitHub
Register on the application and you'll find a lot of extra functionality.
In order to do this I will need phone and pin columns added to the users table with a migration. The logic for authentication will be as follows:
after successful login, is a phone number present?
- if not then normal login
- if yes then:
- generate a pin (not shown to user)
- send off to Twilio
- show a form to enter pin returned by Twilio
- restrict access only if successful login. You don't want people to be able to just go straight to this and then start trying to hack pin codes
If I had another project that I wanted to add the functionality of voting to then I would be better making a Gem. To begin with I need to install gemcutter. Next I have to make sure I exit my current project folder because the Gem is a completely separate project. Then create a new project called voteable-gem and then it needs a gem specification file which I call voteable.gemspec
and it will look as follows:
Gem::Specification.new do |s|
s.name = "voteable_knoxjeffrey"
s.version = '0.0.0'
s.date = "2015-01-23"
s.summary = "A voting gem"
s.description = "A simple gem for counting votes"
s.authors = ['Jeffrey Knox']
s.email = 'knoxjeffrey@outlook.com'
s.files = ['lib/voteable_knoxjeffrey.rb']
s.homepage = "htp://github.com"
end
In a previous post I wrote a post about how to do this and this post goes through some more ways to achieve the same result in a slightly more succint way. In order to use a module in this case I have to define a path in rails in which to find the module. I need to go to application.rb and add in this line of code:
config.autoload_paths += %W(#{config.root}/lib)
This is essentially saying to add the array (%w is a notation to write an array of strings eg %w(foo bar) returns ['foo', 'bar']) into the autoload paths. config.root is the application root path and lib is the folder under this.
Using ajax in rails is similar to how I used method: 'post'
for the vote up/down links in order to generate a form on the fly. In this case, using remote: true
generates html with a date-remote
call. Javascript in rails is looking for that data-remote
call and then attaches itself to the element and converts the given link to an ajax call. An example using my code is helpful to explain:
<%= link_to vote_post_path(post, vote: true), method: 'post', remote: true do %>
I had a case in my postit application where I needed to add voting for both comments and posts. This required some code in my models for Post and Comment to count the votes:
has_many :votes, as: :voteable
def total_votes
up_votes - down_votes
end
def up_votes
self.votes.where(vote: true).size
end
def down_votes
self.votes.where(vote: false).size
end