Tuesday, 23 December 2014

12 Tips of Christmas - 12 Testing your API

12 Tips of Christmas - 12 Testing your API

In our final tip, we're going to take a look at testing our API, which now looks like this

module API
  module V1
    class Posts < Grape::API
      version 'v1'
      format :json

      resource :posts do
        desc "Return 10 most recent posts"

        get do
          posts = Post.most_recent.limit(10)
          present :posts, posts, with: API::V1::Entities::Post
        end

        desc 'Find a specific post'
        params do
          requires :id, type: Integer, desc: "The ID of the post"
        end
        get ':id' do
          post = Post.find(params[:id)
          present :post, post, with: API::V1::Entities::Post              
        end
      end

    end
  end
end

To begin, we want to ensure that our API returns the data we expect it to

# spec/api/v1/post_spec.rb

describe API::V1::posts do
  describe "GET /api/v1/posts" do
    it "returns an empty array of statuses" do
      get "/api/v1/posts"
      expect(response.status).to eq(200)
      expect(JSON.parse(response.body)).to eq({"posts"=>[]})
    end

    it "filters based on names" do
      expected_post = create(:post, content: "Foobar")
      unexpected_post = create(:post, content: "Baz")
      get "/api/v1/posts?content=Foobar"

      expect(response.status).to eq(200)
      expect(JSON.parse(response.body)).to eq({"posts"=>[{"id"=>expected_post.id,
                                                           "content"=> expected_post.content, "created_at"=>"#{expected_post.created_at}"
                                                           }]})
    end
    it "filters based on location id" do
      expected_post = create(:post, content: "Foobar")
      unexpected_post = create(:post, content: "Baz")
      get "/api/v1/posts?place_id=Quas"

      expect(response.status).to eq(200)
      expect(JSON.parse(response.body)).to eq({"posts"=>[{"id"=>expected_post.id,
                                                           "content"=> expected_post.content, "created_at"=>"#{expected_post.created_at}"
                                                          }]})
    end
  end
end

As you can see these function very similar to a request spec and are implemented accordingly. The utilisation of the JSON.parse ensures our content that is exposed matched what we expect.

A simpler version for this is using airborne a Gem designed to not only verify the type of content we return, but the content itself, for example:

it 'should validate types' do
  expected_post = create(:post, content: "Foobar")
  unexpected_post = create(:post, content: "Baz")
  get "/api/v1/posts?content=Foobar"
  expect_json({"posts"=>[{"id"=>expected_post.id,"content"=> expected_post.content, "created_at"=>"#{expected_post.created_at}"}]})
  expect_json_types({id: :integer)
end

So now you have no excuse for not testing your API!

Sunday, 21 December 2014

12 Tips of Christmas - 11 Restricting your API

12 Tips of Christmas - 11 Restricting your API

Yesterday we ended up with the following API. The one issue we have is that we've exposed all of our Post model regardless if we want to or not. 
module API
  module V1
    class Posts < Grape::API
      version 'v1'
      format :json

      resource :posts do
        desc "Return 10 most recent posts"

        get do
          Post.most_recent.limit(10)
        end

        desc 'Find a specific post'
        params do
          requires :id, type: Integer, desc: "The ID of the post"
        end
        get ':id' do
          Post.find(params[:id)
        end
      end

    end
  end
end
Grape provides an easy way to deal with this in the form of entities.
Under our V1 API directory, we're going to create a Post entity, that will restrict the information that comes out of our API
# app/controllers/api/v1/entities/post.rb
module API
  module V1
    module Entities
      class Post < Grape::Entity
        expose :content, documentation: { type: "String", desc: "The Post content"}
        expose :title, documentation: { type: "String", desc: "The Post title"}

        expose :description, documentation: { type: "String", desc: "The Post description" }

        format_with(:iso_timestamp) { |dt| dt.iso8601 }

        with_options(format_with: :iso_timestamp) do
          expose :created_at, documentation: { type: "DateTime", desc: "When the Post was posted"}
        end

        expose :comments, using: API::V1::Entities::Comments
      end
    end
  end
end
With use of the expose method, we can dictate what we do and don't return from our API, as well as provide documentation for users consuming our API. 
When working with building an API initially, I ran into an issue where the datetime returned by my API was different to what was initially coming into the database, the format_with method alleviates this by providing an easy way to declare a format to utilise on a particular attribute, which is picked up in the with_options block.
Finally as our post has many comments we can also expose those to an API request and utilise another entity again to control what of the comment data we return.

Saturday, 20 December 2014

12 Tips of Christmas - 10 Building an API with Grape

12 Tips of Christmas - 10 Building API's with Grape

As I work more and more with Ember, grasping onto well structured API's becomes increasingly valuable. Thanks to Grape, building an API out of your Rails application is very easy.
To start, add grape to your Gemfile, like so and run bundle install
gem "grape"
As we're ultimately serving up a response to requests from the client, we're going to house our API in our controllers directory. As Grape supports versioned API's we're going to keep that structure in place when we begin to create our API. So, first things first, let's create a base.rb file to mount our versioned API's
# app/controllers/api/base.rb

module API
  class Base < Grape::API
    mount API::V1::Base
  end
end
Now let's create our other base.rb file in our V1 directory so we can mount the resources this version of the API will support.
# app/controllers/api/v1/base.rb

module API
  class Base < Grape::API
    mount API::V1::Users
    mount API::V1::Posts
  end
end
Let's also setup our routes to support our new API
# config/routes.rb

mount API::Base => '/api'
This makes our users and posts API available at http://localhost:3000/api/v1/users.json and http://localhost:3000/api/v1/posts.json respectively (assuming you're exporting out JSON).
So let's take a look at what our API's might look like:
module API
  module V1
    class Posts < Grape::API
      version 'v1'
      format :json

      resource :posts do
        desc "Return 10 most recent posts"

        get do
          Post.most_recent.limit(10)
        end

        desc 'Find a specific post'
        params do
          requires :id, type: Integer, desc: "The ID of the post"
        end
        get ':id' do
          Post.find(params[:id)
        end
      end

    end
  end
end
In this very simple example, we declare the version and the format in which we will return.
We also declare the resource we're going to work with, along with our two GET requests we accept, one that returns the 10 most recent posts and one that will return a post determined by the id parameter supplied.
You'll notice that this is starting to look alot like our regular controllers, as well it should. We can also expand on this to start allowing users to make POST and PATCH requests as well.
With our params block , we can specify what parameters we accept as well as in what format they should come, much like Rails' strong parameters.
We also have the ability to document our API as we go with our description methods, this is far far easier to do as you're building up the API so I highly encourage you to do it as you go.
In the next post we'll take a look at restricting the data coming back out of our API

Friday, 19 December 2014

12 Tips of Christmas - 9 Custom Generators

Twelve Tips of Christmas - 9 Custom Generators

With an application template and the assistance of a gem, bootstrapping a brand new Rails app is very easy for us these days. I hadn't realised how spoilt we had become until I had to create one from scratch recently.

One of the nice things in our bootstrap process, is that I have a few generators running to install some custom templates for our application to utilise. Creating a generator command is pretty easy and can be done within a gem or within your own Rails app

We'll use our basic example which is to copy our usual Capistrano configuration templates over to our application folder:

Firstly, you'll need to extend Rails::Generators::Base and give it the root directory of your templates to copy over

class CapistranoConfigGenerator < Rails::Generators::Base
  source_root File.expand_path("../../templates", __FILE__)
end

Then its as simple as creating your methods and using the Thor API to start moving your files over:

class CapistranoConfigGenerator < Rails::Generators::Base
  source_root File.expand_path("../../templates", __FILE__)

  def copy_config_files
    copy_file "config/deploy.rb", "config/deploy.rb"
    directory "config/deploy", "config/deploy"
  end
end

Passing in an additional description, will help new users determine what your generator actually does if they dont happen to look at your code

class CapistranoConfigGenerator < Rails::Generators::Base
  source_root File.expand_path("../../templates", __FILE__)

  desc 'Copies over Capistrano templates'
  def copy_config_files
    copy_file "config/deploy.rb", "config/deploy.rb"
    directory "config/deploy", "config/deploy"
  end
end

The help can be viewed by running (assuming your generator is housed in your Rails application): bin/rails generate capistrano_config --help

Following that, just running the generate command and it'll safely start moving over those files for you

`bin/rails generate capistrano_config`

The flexibility and scope of Thor makes it really easy to accomplish any bootstrapping you may need to do, I highly recommend checking out the documentation

Thursday, 18 December 2014

12 Tips of Christmas - 8 Send Emails with Sidekiq

12 Tips of Christmas - 8 Send Emails with Sidekiq

To help ensure users get a fast experience within your application, one tool you can utilise is Sidekiq to process any sending of email you might be doing asynchronously. 
To get started, just add the following line to your Gemfile
gem 'sidekiq'
You'll also need redis, so if you haven't got that installed run the following:
$ brew update

$ brew install redis

$ redis-server /usr/local/etc/redis.conf
To run Sidekiq:
$ bundle exec sidekiq
Sidekiq supports sending emails with ActionMailer off the bat, all you need to do is call delay before your mailer method instead of using deliver eg:
UserMailer.delay.reminder(@user)
We can also call delay_until to delay the email send until a specified time.
All too easy

Wednesday, 17 December 2014

12 Tips of Christmas - 7 Inversion of Control

12 Tips of Christmas - 7 Inversion of Control

A lot of my posts in this series tend to revolve around a common theme, refactoring. When extracting a class, or method, you should look to inversion of control to make testing, and identification of dependencies easier.
Suppose we had a class like this:
class Receipt
  def mark_purchase
    @purchase = Purchase.latest.first
    enter_purchase_amount @purchase.amount
  end
end
By returning an instance of purchase within the method, we have created an implicit dependency on Purchase, this also makes it harder to test the method without first requiring an instance of the Purchase model. On top of this, we are now tied to the Purchase API, when all we wanted is something that would respond to amount.
Fixing this is easy.
class Receipt
  attr_reader :purchase

  def initialize purchase
    @purchase = purchase
  end

  def mark_purchase
    enter_purchase_amount purchase.amount
  end
end
Now when we instantiate our object, we can give it an instance of any object, so long as that object responds to the amount method, giving us some great flexibility
On top of that, our class can now be decoupled from ActiveRecord within our tests, as all we need to do is provide a test double for a purchase object.
One other benefit is that now, our dependency on purchase is explicit, this assists with future maintainers as they will be able to quickly identify it rather than get surprised down the road.
Of course this example is overtly simple, in our object if we didn't require any other reference to purchase, it would be far simpler to just pass in our amount as a dependency. This example, does however illustrate that by moving the responsibility of assigning the dependency up the chain, we've gained an interface thats more flexible, easier to maintain and easier to test.

Tuesday, 16 December 2014

12 Tips of Christmas - 6 Decorators

One of the really nice things about working with Ember is that every part nicely encapsulates it's level of responsibility. With Rails, this can be a harder proposition, especially when dealing with the view layer. Decorators can alleviate this issue and form our 6th, valuable tip.
We can utilise decorators to move view related logic out of the model, or helper and into the decorator object, we can do this, using SimpleDelegator.
SimpleDelegator accepts an object as part of it's instantiation, and if it can't find a method it will delegate to the underlying object.
class UserDecorator < SimpleDelegator
  def full_title
    "#{title} #{first_name} #{last_name}"
  end
end


class UsersController < ApplicationController
  def show
    @user = UserDecorator.new(User.find(params[:id])
  end
end
Using decorators as a view object, is a very simple option for moving logic out of the business layer that is the model.
Extending this concept, methods within the model that don't explicitly relate to business logic can be moved out and repurposed in a decorator.
class UsersController < ApplicationController
  def index
    @users = UsersDecorator.new(User.all).latest_users
  end
end
The question of where and when to extract this logic, should be dictated by whether or not it falls outside of the responsibility of the object you might decorate it with. I'm a big believer in trying to adhere to Single Responsibility Principle, so this extraction makes a lot of sense.
We want to utilise SimpleDelegator rather than sub-classing our objects as we're not really interested in copying or exposing the base classes API, we just want to copy functionality.

Monday, 15 December 2014

12 Tips of Christmas - 5 Rendering a Hash with OpenStruct

12 Tips of Christmas - 5 Rendering a Hash with OpenStruct

OpenStruct is pretty fantastic, it let's you arbitrarily create attributes, which is fantastic if you have some dynamically generated hashes you need to work with. 
One of the really cool tricks you can do, is take that OpenStruct and render it, this is incredibly useful for sending out text messages, all you need is a little ERB.
to start, create your rendering object:
require 'ostruct'
require 'erb'

class SmsRenderer < OpenStruct  
  def render(template)
    ERB.new(template).result(binding)
  end
end
Now we have an object capable of rendering, all we need to do is give it a template, and a Hash with some attributes, like so:
def sms_template_render file_name, options = {}
  rendering_obj = SmsRenderer.new(options)
  template = File.open("#{Rails.root}/app/views/sms/#{file_name}.text.erb").read
end
Now you can use those lovely erb tags in your text message templates! 
If we just call the above method when passing content to your SMS send method, you'll get the dynamic text messages you're after.

Sunday, 14 December 2014

12 Tips of Christmas - 4 Null Objects

4. Null Object pattern

Sometimes you may find yourself co-opting nil, where we test to see if an object is nil and change the methods behaviour accordingly. Issues can arise right down to the view layer as we constantly check to see if a particular object is nil or not, i.e.: 
- if @membership.present?
  = @membership.plan
- else
  "Guest"
Enter the Null Object pattern.
A good use case for Null Objects are guest memberships, where we need them to conform to the regular membership API, but respond slightly differently.
class GuestMembership
  def active?
    false
  end

  def paid?
    false
  end

  def plan
    "Guest"
  end
end
Now, when we determine what membership is displayed, we make that decision not in the view, but in our model, or other class. This means our view can now look like this instead:
= @membership.plan
The downside to this pattern, is that you now need to maintain two sets of API's, but used sparingly, I really like how this enables me to pull logic out of views and even models, where I query to see if an object exists or not.

Saturday, 13 December 2014

12 Tips of Christmas - 3 Wrap instantiation inside a class method

3. Wrap instantiation inside a class method

Quite often I find myself when creating report objects, wanting to do the following:
@report = Report.new(params)
@report = @report.report()
Why not cut to the chase, by creating a report class method, that returns your shiny instantiated report for you:
class Report

  def self.report(params)
    report = self.new(params).report()
  end
end
Now we can simply call the following, whenever we want a new instance of our report:
@report = Report.report(params)
Much easier.

Friday, 12 December 2014

12 Tips of Christmas - 2 Virtus

2. Use Virtus in your form objects

I love form objects. Stripping away unwanted complexity in our models and housing them in nice neat little packages of code is amazing. Virtus gives me a little extra boost by doing alot of the coercions of my form attributes for me, allowing me to just get on with building the functionality I need. 
To get started, simply plug the virtus gem in your gemfile, and inside your form object (let's say its one of my favourites, a report) add the following:
class UserForm
  include Virtus.model

  attribute :joined_on, Date

  attribute :username, String
end
Now when I initialize the object with a params hash, I don't have to think about getters and setters, or cooercing Dates or DateTimes, I can just pass the params in and have Virtus do the hard work for me. 


Thursday, 11 December 2014

12 Tips of Christmas - 1 Use .map with Rspec

In the Christmas spirit of giving, I wanted to share with you 12 months worth of little tidbits that can help your Rails code. These are all little tips that I have been finding incredibly useful this year, and I'll be releasing one each day right up until Christmas Eve. 

1. Use map when comparing arrays in Rspec

Often when writing tests for a scope, or array equality, we'll end up with something like:
it { expect(User.active).to match_array([user_active, user_guest_active]) }
Of course, when that test fails, we end up with a lot of noise, as the output will give us the object in full. 
An easier way, is to use map to actually get out the information we're interested in:
it { expect(User.active.map(&:first_name)).to match_array([user_active, user_guest].map(&:first_name) }
This way, when we get our output back on our failing tests, it's much easier to determine what is actually wrong with our test as well as make it that much more obvious to the reader what they're looking for in return.