Over the last couple of weeks we’ve looked at getting started with Trailblazer and Ruby on Rails, and Operations and Contracts.

A Trailblazer Operation encapsulates the given action of your application. So far in this little exploration of Trailblazer we’ve created an Operation for creating new Users.

Encapsulating an action in an Operation class is a really nice way of defining the logic for that action. As we saw in Getting started with Operations in Trailblazer, it’s also really easy to test the business logic of the Operation for the given action.

But how do we now use that Operation in the Controller and the View?

In today’s tutorial we will be connecting the dots to finish off the implementation for creating a new user using Trailblazer and Ruby on Rails.

Writing the tests

I’m definitely not a stickler for strict Test Driven Development. More often than not I tend to use the spike and stabalise method of writing code.

However sometimes I do find it beneficial to write out the tests first because it allows me to plan what I need to build. Just the act of writing each incremental test often allows me to get past the mental block of implementing something, even if it is relatively simple.

So with that being said, here are the controller tests that we will be looking to satisfy in today’s tutorial:

require "test_helper"

class RegisterControllerTest < ActionController::TestCase  
test "should display register form" do  
get :new

assert_response :success  
end

test "should fail to register with invalid data" do  
post :create, user: {email: "", password: ""}

assert_response 400  
end

test "should register new user" do  
post :create, user: {email: "name@domain.com", password: "password"}

assert_response 302  
assert_redirected_to login_url  
end  
end  

In the first test I’m asserting that a GET request to the new method of the RegisterController returns a successful response. If this doesn’t return a successful response something has seriously went wrong.

Next I assert that passing invalid data to the create method will return a HTTP response code of 400.

And finally, I will assert that passing valid data to the create method will return a HTTP response code of 302 and we should be redirected to the login URL.

You will notice that I’m not testing every validation rule or circumstance or scenario in these tests. I prefer to test those kinds of things at the Unit level.

With the tests in place, we can now write the code to make them pass.

Adding the routes

The first thing I’m going to do is to add the routes that we require:

Rails.application.routes.draw do  
# Registration  
get "register", to: "register#new"  
post "register", to: "register#create"

# Authentication  
get "login", to: "login#new"  
end  

We’re not going to implement logging in into the application in today’s tutorial, but we need the login route to redirect to on a successful registration attempt.

If you are familiar with routing in Rails this should look fairly straight forward to you. If you are not familiar with routing in Rails, take a look at Defining URL routes in Ruby on Rails.

Adding the Controllers

Next up we can add the Controllers that we will need to make the tests pass.

First create a new file under the controllers directory called register_controller.rb:

class RegisterController < ApplicationController

end  

If you remember back to my review of Trailblazer, a Controller in a Trailblazer application is simply a lean HTTP endpoint that does not contain any business logic.

So first up we can define the new method, which will display the registration form:

class RegisterController < ApplicationController  
def new  
form User::Create  
end  
end  

In this method we simply need to pass the Operation to the form method that was added to the Controller by Trailblazer.

Next we can implement the create method that will accept the POST request to create a new user:

class RegisterController < ApplicationController  
def new  
form User::Create  
end

def create  
run User::Create do |op|  
return redirect_to login_url  
end

render :new, status: 400  
end  
end  

Pretty nice huh? In this method we run the Operation and pass it a block. The block will only be executed if the request is run successfully. I absolutely love how simple Trailblazer makes my Controllers!

Inside the block I’m simply redirecting to the login page. But you could do whatever you want inside this block on a successful registration request.

If the Operation is not successful we can simply render the :new method and set a status of 400.

In this tutorial we’re simply using the login page as a destination for the redirect. So to make this work we will need a Controller and a View:

class LoginController < ApplicationController  
def new

end  
end  

I’ve just left the new method empty for now as we don’t actually have to implement anything in this Controller to make the tests pass.

Adding the Views

Now that we have the Controller methods implemented, we need to add the Views so Rails doesn’t complain.

First I will create a new directory under views called register and a new file called new.html.slim:

h1 Register  
– if @form.errors.any?  
ul  
– @form.errors.full_messages.each do |msg|  
li = msg

= form_for @form, url: register_url do |f|  
div  
= f.label :email  
= f.text_field :email  
div  
= f.label :password  
= f.password_field :password  
div  
= f.submit "Register"  

This is just a simple form for the email and password and a submit button. If the form has any errors we can iterate through them and display them as a list.

We also need a view for the login route. Create a new directory under views called login and then create a new file called new.html.slim:

h1 Login  

Again, we don’t actually need to implement a login form to make the tests pass, so this will be fine for now.

Now with everything in place, you should be able to run the tests and see them all pass! You can also boot up Rails in the browser and go through the registration flow yourself to verify that everything is working correctly.

Conclusion

So as you can see, Trailblazer really does make your Controllers lean HTTP endpoints!

I personally love this aspect of Trailblazer. I hate it when you open a project and the Controllers are totally stuffed with methods and all sorts of weird code to deal with business logic edge cases.

The more I use Trailblazer, the more I appreciate this style of architecture for medium to larger sized applications.