Blog Archives

Sharing code in FactoryGirl

Posted in Code, Inside TFG, Ruby on Rails, Tips and Tricks

Sharing Code

Sharing code between factories in FactoryGirl takes a little bit of effort. Here’s one way of accomplishing it, which I patched together from reading this GitHub Issue:

Sharing code in FactoryGirl

First, we create a module with the shared code. Then we include it into the FactoryGirl::SyntaxRunner.

You need to put it in the spec/factories folder so that it is included when FactoryGirl is included. I put it in a subfolder spec/factories/support/ so that it is easy to differentiate between the factories and the supporting files.

So you might have a file like below:

# spec/factories/support/random_code_support.rb

# I use a namespace here so there's no chance of overriding any other class or module.
module FactoryGirlSupport
  module RandomCodeSupport
    def generate_random_code(i, min_length=6)
      rand(1000).to_s.rjust(min_length, "0") + i.to_s
    end
  end
end

# This will make the methods in the FactoryGirlSupport::RandomCodeSupport available in your factories
FactoryGirl::SyntaxRunner.send(:include, FactoryGirlSupport::RandomCodeSupport)

Now you can use the method in the module above in your factories like this:

FactoryGirl.define do
  factory :user do
    sequence(:remote_id) {|i| generate_random_code(i) }
  end
end

That’s all there is to it.

Refactoring rails controllers the right way

Posted in Code, Inside TFG, Ruby on Rails, Tips and Tricks

Rails developers will often live by the mantra “Skinny Controller, Fat Model” when writing Rails controller code.

At first it can seem like a fairly reasonable practice. The examples in Darcy Laycock’s SitePoint article “10 Ruby on Rails Best Practices” are a great example of this. Another good example is Jamis Buck’s 2006 article “Skinny Controller, Fat Model”.

However, the name of the pattern is misleading and reinforces the noxious idea that any class should be “fat”.

In this article I will discuss ways that we can refactor Rails controllers that will not cause bloat in any models.

Skinny Controller, Fat Model

The “Skinny Controller, Fat Model” practice often results in code in controllers being moved into a model. This reduces the complexity of the controller and moves the responsibility of managing instances of the model back into the model itself. For example, if we have the following controller:

class EventsController < ApplicationController
  before_action :authenticate_user!
  after_action :verify_authorized

  def approve
    @event = Event.find(params[:id])
    @event.state = :approved
    @event.approved_at = Time.now
    @event.approved_by = current_user
    @event.save!

    redirect_to(root_path)
  end
end

The specs for the controller might look a bit like:

require 'rails_helper'

describe EventsController do
  describe 'PATCH approve' do
    subject { patch :approve, id: event.id }

    let(:event) { FactoryGirl.create(:event, approved: false) }

    context "when authenticated && authorized to approve the Event" do
      sign_in_as(:administrator)

      describe "approving the Event" do
        let(:current_time) { Time.now }

        before { Timecop.freeze(Time.local(1990)) }
        after  { Timecop.return }

        specify { expect { subject }.to change { event.reload.approved? }.to(true) }
        specify { expect { subject }.to change { event.reload.approved_by }.to(current_user) }
        specify { expect { subject }.to change { event.reload.approved_at }.to(current_time) }
      end

      it { should redirect_to(root_path) }
    end

    context "when not authenticated to approve the Event" do
      it_behaves_like "a controller action that has failed an authentication check"
    end

    context "when not authorized to approve the Event" do
      sign_in_as(:public_user)

      it_behaves_like "a controller action that has failed an authorization check"
    end
  end
end

The “Skinny Controller, Fat Model” practice might be followed by moving the approval code into the model, leaving the controller looking something like:

class EventsController < ApplicationController
  before_action :authenticate_user!
  after_action :verify_authorized

  def approve
    @event = Event.find(params[:id])
    @event.approve!(current_user)

    redirect_to(root_path)
  end
end

The process of approving an Event has been abstracted and defined in the Event model. Not only is our controller easier to understand, but the approval process is now re-usable and our tests for the controller are easier to write. For example, we could stub out the approve! method rather than having to check all the side effects of approving an Event. Here’s what our controller specs might look like now:

require 'rails_helper'

describe EventsController do
  describe 'PATCH approve' do
    subject(:approve_event) { patch :approve, id: event.id }

    let(:event) { FactoryGirl.create(:event, approved: false) }

    context "when authenticated && authorized to approve the Event" do
      sign_in_as(:administrator)

      it "approves the Event" do
        expect(event).to receive(:approve!).with(current_user)
        approve_event
      end

      it { should redirect_to(root_path) }
    end

    context "when not authenticated to approve the Event" do
      it_behaves_like "a controller action that has failed an authentication check"
    end

    context "when not authorized to approve the Event" do
      sign_in_as(:public_user)

      it_behaves_like "a controller action that has failed an authorization check"
    end
  end
end

However, there is a cost. The Event model has grown larger and the number of responsibilities in the Event model has increased. This makes the class harder to understand, which in turn means that:

  • The risk of defects being introduced is increased
  • Refactoring the class is more difficult
  • Tests are harder to read and write. When tests are hard to write, lazy developers sometimes “forget” to write them.
  • Most importantly: The code becomes a pain in the ass to work on

To prevent bloating our model, this workflow needs to be encapsulated in another class.

Encapsulating the workflow in a model

My preference for encapsulating such a workflow is to create another class. I just think of this class as another model, but some folk prefer to call them domain objects. Here’s a decent explanation from StackOverflow.

In the example above, I’d create a model called Event::Approver to encapsulate approving an Event.

I nest Event::Approver under Event because it is a subset of the workflows in the application that are related to the Event model.

Due to the way that Rails loads files, the file will need to be in the folder app/models/event. This is convenient since I can now look in this folder to find any workflows related to the Event model.

The Event::Approver model will look like:

class Event::Approver

  attr_reader :approver, :event

  def initialize(event, approver)
    @approver = approver
    @event = event
  end

  def approve!
    event.status = :approved
    event.approved_at = Time.now
    event.approved_by = approver
    event.save!
  end

end

The specs for this model will be equally concise, looking something like:

describe Event::Approver do
  describe "#approve!" do
    subject { Event::Approver.new(event, user).approve! }

    let(:event) { FactoryGirl.create(:event, approved: false) }
    let(:user)  { FactoryGirl.create(:user) }
    let(:current_time) { Time.now }

    before { Timecop.freeze(Time.local(1990)) }
    after  { Timecop.return }

    specify { expect { subject }.to change { event.reload.approved? }.to(true) }
    specify { expect { subject }.to change { event.reload.approved_by }.to(user) }
    specify { expect { subject }.to change { event.reload.approved_at }.to(current_time) }
  end
end

The implementation of this class is not especially important. For example, some developers will prefer not to use an initializer and will pass the event and approver directly into the approve! method.

This class is easy to understand as it has a single responsibility. The class is small enough that I can read it and understand it in only a few seconds. I don’t need to search in some 800 line of code Event model for this single method.

Similarly, the tests for the class are straight forward and easy to read and understand. The test file will be quite small, as opposed to the colossal test file that exists for the Event model.

One of the less thought about features of composing classes this way is that if I need to look at the git history for this class, 100% of the commits will be related to this single piece of functionality. I recently found out that is invaluable for when you need to work out why a process has changed. Imagine sifting through all the commits on the Event model trying to work out where function X changed (yeah, I know you can use grep – but what if the method name changed? A pain in the ass, for sure).

With our new model the controller would now look slightly different than before, but is just as skinny:

class EventsController < ApplicationController
  before_action :authenticate_user!
  after_action :verify_authorized

  def approve
    @event = Event.find(params[:id])
    Event::Approver.new(@event, current_user).approve!

    redirect_to(root_path)
  end
end

In defence of “Skinny Controller, Fat Model”

To be perfectly honest, I doubt the intention of “Skinny Controller, Fat Model” is to just blindly jam all your controller code into ActiveRecord models. I suspect it’s more likely that it means “Skinny Controllers, Fat Model Layer”.

That being said – I think it is all too easy for inexperienced developers to take the phrase literally and do just that. In fact, I have six years of experience working with developers who have zealously bloated ActiveRecord models to prevent controllers from having more responsibilities. Including myself for a time.

In summary…

When it comes to refactoring, cleaning up a controller doesn’t really benefit the health of your application if it causes a model to get dirtier.

Rather than adding more and more responsibilities to ActiveRecord models, we can create new single-purpose classes (domain objects, if you like) to encapsulate these workflows.

By doing this we make smaller classes that are easier to understand, easier to maintain, and easier to test.

Further Reading:

  1. “”Fat model, skinny controller” is a load of rubbish” by Jon Cairns
  2. “Skinny Controllers, Skinny Models” by Joe Ferris

Handling race conditions with Rails’ pessimistic locking

Posted in Code, Ruby on Rails, Tips and Tricks

I recently worked on a Rails application where race conditions were causing issues in the background tasks operating on my ActiveRecord objects. In this article I will explain how I used pessimistic locking to get around these issues.

Defining an example

Firstly, consider a sample Rails application with the following features/rules:

  1. Administrator can see a list of clients;
  2. Administrator can visit the client’s profile page and send an SMS to the client;
  3. Administrator cannot send more than one SMS to each client per day;

Let’s keep the implementation as simple as possible. Consider a Client model with an attribute last_sms_sent_on and the following class (which can be used by a controller or a Sidekiq task):

class ClientSMSSender
  def self.perform(client, message)
    client.transaction do
      if client.last_sms_sent_on.blank? || !client.last_sms_sent_on.today?
        client.last_sms_sent_on = Date.today
        client.save
        SMSGateway.send(client.phone_number, message)
      end
    end
  end
end

Analysing the race condition issue

Imagine that there are some external issues and SMSGateway.send hangs for an average of 30 seconds. In this meantime another administrator makes a new request to send an SMS to the client. Due to race conditions we’ll end up sending more than one message to the client on the same day.

This is what will happen:

  1. Administrator A makes a request (Request A) to send an SMS to the client
  2. Client has not received any messages today
  3. Request A is hanging due to external issues
  4. Administrator B make a new request (Request B) to send the same SMS to the client
  5. Client has not received any messages today (the Request A still hanging)
  6. Request B is hanging due to external issues as well
  7. Request A finishes and client.last_sms_sent_on is updated
  8. Request B still holding the previous state of the client object
  9. Request B finishes, send the SMS again and re-update client.last_sms_sent_on

Work around

In order to work around that issue, you can make use of the method with_lock from ActiveRecord::Locking::Pessimistic.

Have a look at the code below:

class ClientSMSSender
  def self.perform(client, message)
    client.with_lock do
      if client.last_sms_sent_on.blank? || !client.last_sms_sent_on.today?
        client.last_sms_sent_on = Date.today
        client.save
        SMSGateway.send(client.phone_number, message)
      end
    end
  end
end

Under the hood, with_lock:

  1. opens up a database transaction
  2. reloads the record (in order to obtain the last state of the record)
  3. requests exclusive access to the record from the database

When using with_lock: 

  1. Administrator A makes a request (Request A) to send an SMS to the client
  2. Request A locks the client record in database
  3. Client has not received any messages today
  4. Request A is hanging due to external issues
  5. Administrator B make a new request (Request B) to send the same SMS to the client
  6. As the client is currently locked by Request A, the Request B hangs until the database releases the record
  7. Request A finishes and client.last_sms_sent_on is updated
  8. Database releases the client record
  9. Request B (was hanging and waiting for database) now starts the execution
  10. Request B locks the client record
  11. Request B reloads the client record in order to obtain the latest state of the object
  12. Client has already received a message today
  13. Request B finishes without sending a new SMS.

If you’re still confused about that, here’s an easy way to see how with_lock works from your Rails console:

  1. Grab any existing Rails project and open up two Rails consoles
  2. In the first console execute the following:
    u = User.first
    u.with_lock do
      u.email = "test@thefrontiergroup.com.au"
      u.save
      sleep 40 # emulates a very slow external process
    end
    
  3. In the second console execute:
    u = User.first
    u.email = "test2@thefrontiergroup.com.au"
    u.save
    

You’ll notice in the second console that the execution of u.save will hang until the first console finishes the whole process.  You should be careful not to lock your entire app unnecessarily, otherwise you’re likely to introduce a new bottleneck.

Conclusion

The method with_lock is handy, but use it sparingly. Sticking with_lock everywhere might bring you good business logic consistency, but it can come at the expense of performance.

Reflecting on RubyMotion Experiences – Part 2

Posted in Code, Inside TFG, iOS, RubyMotion, Tips and Tricks

As part two of our series, Tony Issakov offers a few thoughts when developing on RubyMotion.

rubymotion

Whilst I spend a lot of time in a management role, I’m a developer at heart that cannot stop developing. Here’s a few things that I’ve come across in the RubyMotion space that may be of use.

1: Know the code you are building on

RubyMotion is a relatively young space that is filling quickly with enthusiastic Ruby developers. New gems are coming out regularly to carry over what we know from our native Ruby world and also to make new iOS capabilities more comfortable to access.

One thing to be aware of is that being a new space there are some fairly fresh pieces of code being integrated into common use and some of them haven’t had much time to mature. For this reason I suggest taking a moment to get to know the gems you are about to use.Octocat

Just as with any code, Github gives us a good place to start, checking out the most recent commit activity, the scale of the issues and hopefully checking that there’s a test suite. Whilst testing isn’t as fully fledged for RubyMotion, an attempt to test is a great start.

Reviewing how code is written has also been very informative. If you want to get some diverse exposure, start looking through BubbleWrap, the ever growing mixed bag of RubyMotion functionality. You can see anything from how to leverage the Camera through to observers with the Notification Centre. It gave me some ideas as a ruby developer of what iOS topics I needed to start researching.

2: Memory Matters

One major change moving into the RubyMotion space from a Rails one is that it’s no longer a stateless environment, pages aren’t a regularly discarded entity and what you do over time can mean something. If you don’t know about reference counting in iOS and the commonly mentioned ARC, it’s worth doing a little homework to understand what RubyMotion is doing for you. Apple provides some documentation explaining memory management, here.

One example of why it’s good to know this is I hit a show stopping moment when I started attaching view content from an 3rd party framework to my own controller objects using instance variables. The external library counted on the releasing of those objects as the app moved through multiple sessions and I was inadvertently retaining them. This ended up in some interesting crashes and the word ‘release’ is a real give away.

A protip here (offered initially to me by Jordan Maguire) was to leverage the dealloc method. If you override a class’s dealloc method, clear up your instance variables, put in a bit of logging whilst you are there and then call out to super, in theory your RubyMotion console should give you a bit of feedback that your app is being healthy about releasing it’s memory.

Another key object to figure out for this topic is WeakRef.

The need for WeakRefs comes up when you start passing delegates around and begin to form cyclic references which if not handled well, can in the least cause memory leaks. Wrapping an object in a WeakRef object gives you a programmatic way of ensuring you release an object and again look to the console for that dealloc feedback.

3: Think ‘Performance’

One of the major benefits of RubyMotion is taking a lot of ruby ideas for making code easy to write. One catch is that a lot of layers of abstraction can create the opportunity for a performance hit.

We saw this first hand when first trying gems like Teacup (a gem for layout and styling). When the gem was pretty young, people using it noticed their apps start to grind and scrolling through tables suffered a stutter. This came down to doing things in a programmatic but performance expensive way when styling table cells. From what I’ve seen many of these issues have been resolved and that has come down to both gem improvements and better patterns for developers applying code in a performance friendly way.

One paragraph that really stuck in my head on this topic was reading through the Queries section of the CDQ gem README. CDQ is a slick Core Data helper and the paragraph reads:

Core Data is designed to work efficiently when you hang on to references to specific objects and use them as you would any in-memory object, letting Core Data handle your memory usage for you. If you’re coming from a server-side rails background, this can be pretty hard to get used to, but this is a very different environment.

This sums up my very first moments of walking into RubyMotion from rails which was iOS persistence is handle by Core Data therefore Core Data equals ActiveRecord. We keep pushing the point but it’s not that Core Data isn’t ActiveRecord, its that things like persistence and what it means to each environment are very different.

4: IDE is not a bad word

Vim versus Emacs? How much finger twister can you play to do fairly amazing things with your editor? I’ve been sucked into this a few times over the years and will admit I find myself in the vim space largely because it was the editor I was raised on. In recent times I followed the Textmate to Sublime migration too. For a time though I found myself in the Java community working with IBM’s Application Developer and that’s where I came to terms with what an IDE is.

When I started to explore RubyMotion and got sucked into the “What editors can I use next?” game, I dabbled with RubyMine and was a little surprised. IDEs for me in the past have meant memory bloat and user interface lag but the JetBrains guys have done a great job optimising resource usage and letting you customise behavior.

Ruby_on_Rails_IDE____JetBrains_RubyMine

Why bring this up for RubyMotion? For many who are looking for some form of visual assistance, a nice refactoring capability, a debugger that is interactive, a spec runner that is visual, this might be a good tool for you to consider to give you a safety-net as you develop. This is absolutely not for everyone but I generally take all the help I can get and regularly swap back and forth between command line and visual tools depending on the task at hand.

5: The simulator is not the device

The iOS simulator is rather amazing in what it offers. A highly performant version of the device that you can swap between device types, screens, resolutions and even simulate events with. With all this it does lure you into believing it’ll be an effortless trip to the device but we found there are a few catches.

The first was that sometimes the simulator outperformed the phone and this is due to the simulator having the full resources of the host available to it. A few of our animations that were smooth on the simulator stuttered slightly and it was during a series of changes that it occurred.iOS_Simulator_User_Guide__About_iOS_Simulator

Another situation was when using external Objective C libraries, it’s possible for the library to have different branches of code depending on the environment meaning that the code you run in the simulator is not necessarily the code you will run on the device. In one extreme case we actually needed to set some custom build flags for the app to even compile for the device.

So the recommendation here is run on the device and frequently enough that if the app has some unusual explosion you aren’t left wondering which of the many gems you just added or commits you just made has cause the issue.

RubyMotion: Under the hood

Posted in Code, iOS, RubyMotion, Tips and Tricks

Some time ago I was working on a RubyMotion app and was called over to look at a colleague’s screen only to find an amazing visual.

Just as Firefox jumped on to the scene with a 3D view of a web page, the team at RevealApp presented to me an exploded view of one of our RubyMotion iOS apps. 3D rotation of many wired frame borders and the ability to click through the views to review settings was amazing. Since then a few new players have come along so here’s a quick recap of how you might see what’s going on under the hood.

1: SugarCube

https://github.com/rubymotion/sugarcube

As a very light weight entrant to the field, SugarCube is a RubyMotion gem that provides a lot of syntactic sugar and utility methods. It includes a nice little command called ‘tree’. This was one of the first mechanisms I ever used in gaining insight into how my app was being put together and is still a bit of a reflex when digging around in the console.

This means of seeing the UI structure in code might be a little harder to interpret at first but it’s nice that without any other frameworks or apps you can see what’s going on.

1__bundled_rake_BUILD_ENV_development_frank_symbiote__sim_

So to sum it up, it’s a console tool with a super easy install and requiring no external software to review the results. This is a great place to start debugging your views.

2: Motion Xray

https://github.com/colinta/motion-xray

Stepping up the visual feedback is Motion Xray. This is the only gem I haven’t personally used but I’ve included it as it’s purpose is to get insight into the current view of the app, in the app itself.

This brings a great level of portability as there’s no need for bridging between external software and internal frameworks. It’s all just in the app. It does make me a little nervous that to view my view code I’m changing my view code but I can see the niche that this plugin aims to fill.

motion-xray

3: Frank and Symbiote

http://www.testingwithfrank.com/

This one really surprised me. Working with Frank is something we’ve been dabbling with for years and it’s definitely growing on me as I feel the need to gain more confidence in how my user interface is behaving. In the past I’ve used the calabash console to help me understand how to access view components for my tests but I recently stumbled on Symbiote which is part of Frank.

Frank opens up a communications gateway for sending tests to the device or simulator and Symbiote piggy backs this getting a full view of what the interface looks like on demand. This in itself is impressive but it then renders that out to a webpage with an interactive console.

This tool is tailored towards making writing tests easier but I loved that it was a means of seeing my app state with just a browser on the side. My experience with it so far has been limited but there is definite potential.

Check out this article (Inspect the State of Your Running iOS App’s UI With Symbiote – Pete Hodgson) for a really great overview of this.

Frank is very easy to install, and so in turn was Symbiote.

Symbiote

4: Reveal App

http://revealapp.com/

This is where the excitement began and at the fully fledged highly visual editor end of the spectrum. A separate app is run to do all the viewing and editing. A framework gets included in your app to open up a bridge for communication (much like Frank).

I found in the early beta stages when I was heavily using this, there were occasional connection issues. The framework broadcasts its presence via Bonjour so you should see your device or simulator appear in the list of possible connections. This type of connection process (when it worked) was nice and simple when moving between device and simulator as there were no config files or settings to worry about.

Once in the app with your screen wire framed and ready for editing, the ability to see and change things is phenomenal. Anyone who is used to tweaking the visuals of a web page at a browser console will feel right at home with this kind of tool. Nudging UI by pixels, changing colouring, messing with opacity. All of these are ready to go.

The only downside to this product has been it’s final price. The licensing is not cheap but so far in my experience this is by far the most powerful tool of its kind.

Reveal_App

5: Spark Inspector

http://sparkinspector.com/

After loving Reveal App I took a quick moment to see what else was out in this space and was stunned to find another contender. Spark Inspector at this time feels like a lighter weight version of Reveal. It’s not as fully loaded with features and modifiable fields but it does have a lot of the key parts like a very visual 2D and 3D representation of your app.

I found that the cocoapod installed without any issues, the connections worked first time and generally this was actually a little easier to get going than my early RevealApp experience. The main area of weakness at this time is that not everything is as easy to access and edit as I found in Reveal. It does feel like you can get a little out of sync with the remote UI and it has a few more general quirks as you modify values.

The major redeeming factor to this is it’s price. At time of writing Reveal cost a bit over four times the price of Spark Inspector so if you find Reveal is out of your budgetary league, this may be an alternative.

Spark_Inspector_and_Spark_Inspector_-_Runtime_Inspection_for_iOS_Apps

6: iOS Hierarchy Viewer

https://github.com/glock45/iOS-Hierarchy-Viewer

As a last minute entrant I was really impressed to stumble over this git repo that looks to be doing things a lot like Symbiote using a web page as the external viewing tool. Looking over the Readme it feels like the install will be harder to get through than Spark or Reveal but there’s a cocoapod and it turned out to be rather painless.

The UI is raw in appearance but comprehensive in details. It feels very much like an insight into the state of the UI rather than the editable side that Reveal gives you.

One surprised was the Core Data addition which with an additional line of code gives you a quick view of the state of your data. Having recently been using cdq I tested this and it worked just as expected showing me a table of my data. This is a very interesting addition putting that little bit more at your finger tips but the lack of edit on the views does make this app more about insight than nudging visuals into place.

In Summary

It’s wonderful to see such a diverse set of tools becoming available to developers. Between a RubyMotion console and the many tools on offer, a developer can get a quick understanding of the visual architecture they are working within and even nudge it in the right direction before making a final change. Given we at times rely on the default apple controls and views it’s also good to understand exactly why things are placed where they are or how many views really do make up a button.

As I was writing this article I found this stack overflow thread covering this topic and picking up pretty much all of the above mentioned tools so if you are looking to hear how some others have found these tools, this may be a place to start.

Also as one closing pro-tip – don’t run too many of these together as not surprisingly my app got a little unstable when spinning up the simulator and multiple apps all tried to start up servers and broadcast messages. Also keep in mind that running the specs instance of a RubyMotion app might clash with your main app if you are swapping back and forth.  If things start to misbehave you might need to restart your simulator or close down apps that are in the background.

If you know of any other apps that haven’t been discussed, let us know.

Search Posts

Featured Posts

Categories

Archives

View more archives