Blog Archives

Using FactoryGirl to easily create complex data sets in Rails

Posted in Code, Inside TFG, Ruby on Rails

I use FactoryGirl for setting up data in my application. FactoryGirl gives you all the tools you need to quickly and easily create data for models in your application. Leveraging ffaker you can make realistic looking, randomized data.

Often, you will have complex associations between objects in your system that can be a pain to factory up. I’ve frequently seen people use individual factories to build up these relationships. The amount of work required to set these associations up quickly gets tedious and turns your code into an unreadable mess.

In this article, I will run through some features of FactoryGirl that you can leverage to easily create complex associations.

Transient Attributes

One of the features I use most in FactoryGirl is the transient attributes. Transient attributes allow you to pass in data that isn’t an attribute on the model. I frequently use transient attributes to allow me to use a single FactoryGirl call to create multiple objects.

For example, say you have two models, User and Role. A User has one Role. You might do something like:

role = FactoryGirl.create(:role, name: “Head Buster”)
user = FactoryGirl.create(:user, role: role)
 

Using transient attributes you could define the following factory:

factory :user do
  transient do
    role_name “admin”
  end

  role do
    Role.find_by(name: role_name) || FactoryGirl.create(:role, name: role_name)
  end
end

which would then allow you to do:

user = FactoryGirl.create(:user, role_name: “Head Buster”) 

Traits

Another of my favourite features is traits. You could solve the scenario above using traits by doing something like:

factory :user do
  trait :head_buster do
    role do
      Role.find_by(name: “Head Buster”) || FactoryGirl.create(:role, name: “Head Buster”)
    end
  end
end

which would then allow you to do:

user = FactoryGirl.create(:user, :head_buster)

I’ve found that the power of traits expands exponentially with the complexity of the model they are trying to map. The more states your model can be in, and the more data it has attached to it, the more you’ll be able to use traits to simplify data creation. Try to abstract any state that an object can be in into a trait to simplify usage.

Callbacks

Callbacks in FactoryGirl are also extremely useful. They work hand in hand with transient attributes and traits to allow you perform any non-obvious setup in your factories.

Let’s imagine an app which has the following models:

  • User
  • Book
  • UserReadBook (Join between User and Book, indicating the user has read this book)
  • WishlistBook (Join between User and Book, indicating the user added this book to their Wishlist)

Out of the box, if you wanted to create one of each type of object, you might have some FactoryGirl calls like:

user = FactoryGirl.create(:user)
book = FactoryGirl.create(:book)
FactoryGirl.create(:user_read_book, user: user, book: book)
FactoryGirl.create(:wishlist_book, user: user, book: book)

Let’s say we have a function on User: #related_books, which returns all Books that the User has read or added to their wishlist. Our RSpec tests for such a function might look like:

describe '#related_books' do
  subject(:related_books) { user.related_books }
  let(:user) { FactoryGirl.create(:user) }

  it "includes books this user has read" do
    expect(related_books).to include(FactoryGirl.create(:user_read_book, user: user).book)
  end
  it "includes books this user has added to their wishlist" do
    expect(related_books).to include(FactoryGirl.create(:wishlist_book, user: user).book)
  end
  it "doesn't include books read by other users" do
    expect(related_books).to include(FactoryGirl.create(:user_read_book).book)
  end
  it "doesn't include books other users have added to their wishlist" do
    expect(related_books).to include(FactoryGirl.create(:wishlist_book).book)
  end
end

Doesn’t look TOO bad. I REALLY don’t like having to tack the .book on the end there. I also don’t like that I’m not directly creating the type of object I want returned in my test. Personally, I think it makes the tests harder to understand. The bigger problem is when we need to refactor.

What happens when requirements change and we have to add in a VideoGame model? Now we change the UserReadBook and WishlistBook models to be polymorphic so they can also hold VideoGames. As a result, we rename the models to UserCompletedItem and WishlistItem.

It’s extremely likely we’ll used the original join table factories in multiple places to test other scopes, searching functions, and more. As a consequence, we have to update all our specs to use the updated join table name. Doesn’t this last step seem like an unnecessary pain in the ass?

What we should have done is used our factories to abstract the concept of wishlisting or reading a Book. Our tests generally want to ensure that there is a specific type of relationship between a Book and a User, but they shouldn’t really need to care about the specifics of it. Let’s look at how factories can help us.

The first thing I do when trying to abstract these concepts is work out the interface I want in my factories. In the case above, I’d like to be able to write:

FactoryGirl.create(:book, read_by: user) # and
FactoryGirl.create(:book, wishlisted_by: user)

I can support this interface using transient attributes and factory callbacks. I can update to my Book factory to look like:

FactoryGirl.define do
  factory :book do
    transient do
      read_by nil
      wishlisted_by nil
      # nil is a sensible default, we don't want our factories creating
      # extra data unnecessarily. It slows your test suite down
    end

    after(:create) do |book, factory|
      if factory.read_by
        FactoryGirl.create(:user_read_book, book: book, user: factory.read_by)
      end
      if factory.wishlisted_by
        FactoryGirl.create(:wishlist_book, book: book, user: factory.wishlisted_by)
      end
   end
 end
end

Here’s what I like about abstracting the concept of reading or wishlisting a Book using factories:

Simpler Tests

Our tests are no longer loaded with implementation details of joining the Book and User. This is especially useful in even more complex relationships. Basically, if my test is checking that a book is returned, I only ever want to create a Book. I don’t want to have to creating multiple other models.

Reduced cost of refactoring

When we have to update the join between Book and User, we only need to update one factory instead of every test that had instantiated one of the renamed join tables.

More concise tests

Although in my example I used a one liner for getting a read or wishlisted Book, in reality the syntax you’d probably see is:

user = FactoryGirl.create(:user)
book = FactoryGirl.create(:book)
FactoryGirl.create(:user_read_book, user: user, book: book)
FactoryGirl.create(:wishlist_book, user: user, book: book)

Which with the factory above could be reduced to:

user = FactoryGirl.create(:user)
book = FactoryGirl.create(:book, read_by: user, wishlisted_by: user)

This may not seem like much, but it can build up. Recently I made a similar refactoring in a spec file that contained 10 such blocks. That amounted to 20 fewer LoC or around 5% fewer LoC in the spec file. Also, had a written my factory in that way in the beginning I would had to type a hell of a lot less, too.

Here’s what my specs would look like with my updated factories:

describe '#related_books' do
  subject(:related_books) { user.related_books }

  let(:user)       { FactoryGirl.create(:user) }
  let(:other_user) { FactoryGirl.create(:user) }
  it "includes books this user has read" do
    expect(related_books).to include(FactoryGirl.create(:book, read_by: user))
  end
  it "includes books this user has added to their wishlist" do
    expect(related_books).to include(FactoryGirl.create(:book, wishlisted_by: user))
  end
  it "doesn't include books read by other users" do
    expect(related_books).to include(FactoryGirl.create(:book, read_by: other_user))
  end
  it "doesn't include books other users have added to their wishlist" do
    expect(related_books).to include(FactoryGirl.create(:book, wishlisted_by: other_user)
  end
end 

Wrapping up

So using traits, transient attributes, and callbacks we can make our FactoryGirl factories do a lot more of the heavy lifting for us.

We can also abstract complex associations to reduce the cost of refactoring and increase the readability of our tests.

Although those are my favourite feature, they don’t cover everything FactoryGirl offers. I’d recommend going through the FactoryGirl documentation and thinking about what you can do to get more out of factories in your code.

 

A quick tip with .Net generics

Posted in Code, Inside TFG

Generics constraints in .Net can be recursive. This means that you can use a type in its own generic constraints. Let’s look at an example of where this can be useful.

Let’s say you have some kind of persistent object IEntity. To avoid primitive obsession we are going to create a type safe Reference<T> object to act as a pointer to our entities, rather than just having a property of int called Id.

IReference<TEntity>
where TEntity : IEntity
{
// Actual interface doesn't matter
}

We want a base entity to inherit from, which among other things exposes an IReference<T> to itself.  We can’t be much more specific than returning an IReference<EntityBase>, since we can’t know the subclass type at compile time. Unless we hail to the generic recursion gods.

EntityBase<TSelf> : IEntity
where TSelf : EntityBase<TSelf>
{
IReference<TSelf> Reference { get { ... } };
}

Now we just supply the type when we declare our subclass:

MyEntity : EntityBase<MyEntity>
{
}

You can do much the same thing in Java, but it’s not quite as safe since MyEntity extends EntityBase<OtherEntity> will compile just fine.

As an exercise to the reader; consider the visitor pattern, where we implement a virtual Accept method in order to have compile time type knowledge of this. Can you now write a non virtual Accept method?

A look at Cayley

Posted in Code, Inside TFG

Recently I took the time to check out Cayley, a graph database written in Go that’s been getting some good attention.

Cayley Logo

https://github.com/google/cayley

From the Github:

Cayley is an open-source graph inspired by the graph database behind Freebase and Google’s Knowledge Graph.

Also to get the project owners disclaimer out of the way:

Not a Google project, but created and maintained by a Googler, with permission from and assignment to Google, under the Apache License, version 2.0.

As a personal disclaimer, I’m not a trained mathematician and my interest comes from a love of exploring data. Feel free to correct me if something should be better said.

I’ve seen Neo4j.. I know GraphDB’s

Many people exploring graph databases start with Neo4j and conceptually it’s similar but in usage terms there is a bit of a gap.

Neo4j has the Cyper query language which I find very expressive but also more like SQL in how it works. Cayley uses a Gremlin inspired query language wrapped in JavaScript. The more you use it the more it feels like writing code based interactions with chained method calls. The docs for this interface take some rereading and it was only through some experimentation that I started to see how it all worked. They can be accessed via the Github docs folder. I worked my way through the test cases for some further ideas.

Another major difference is that in Neo4j it’s a bit of a gentler transition from relational databases.  With Neo4j you can group properties on nodes and edges so that as you pull back nodes it feels a little more like hitting a row in a table. Cayley, however, is a triple / quad store based system so everything is treated as a node or vertex. You store only single pieces of related data (only strings in fact) and a collection of properties that would traditionally make up a row or object is built through relationships. This feels extreme at first as to get one row like object you need multiple traversals but over time for me it changed how I looked at data.

unnamed0_-_yEd

As an example (ignoring the major power of graph databases for starters) we might have the question “What is user 123’s height”. In Neo4j we can find a person with id 123, pulling back a node with that person’s name and height. We can then extract the height value. In Cayley you could find the persons id node and then move via the height relationship to the value 184. So in the first case we are plucking property data from a returned node. In the second we collect the information we want to return. This is more a conceptual difference than a pro or a con but it becomes a very clear difference when you start to import data via quad files.

What is an  n-quad?

As mentioned Cayley works on quads / triples which are a simple line of content describing a start, relationship and finish. This can be imagined as two nodes joined by an edge line. What those nodes and relationships are can be many things. Some people have schemas or conventions for how things are named. Some people are using URLs to link web based data. There is a standard that can be read about at www.w3.org:

http://www.w3.org/TR/n-quads/

A simple example might be from the above:

"/user/123" "named" "john" .
"/user/124" "named" "kelly" .
"/user/124" "follows" "/user/123" .

When is a database many databases?

One of the tricky parts of a graph database is how to store things. Many of the graph dbs out there don’t actually store the data but rather sit on an existing database infrastructure and work with information in memory. Cayley is no different as you can layer it upon a few different database types – LevelDB, Bolt, MongoDB and an in memory version.

An interesting part of this is the vague promise of scaling. Most graph databases start off the conversation with node traversal, performance, syntax but they almost all end in scaling. I think Cayley is now entering this territory. As it moves from a proof of concept to something that gets used more heavily, it’s acquiring backends that can scale and the concept of layering more than one Cayley instance in front of that storage layer.

One think to keep in mind is performance is a combination of how the information stored and accessed so put a fast graph db in front of a slow database and you’ll average out a little in speed. For my testing I used a built in leveldb store as it is built in and easy to get started with.

Show me the graph!

One of the first issues I had with Cayley was not 100% knowing how to get graph to page. Neo4j spin up was a little clearer and error handling is quite visual. Cayley you have to get syntax and capitalisation just right for things to play nicely.

Lets assume you have the following graph:

graphy

Node A is connected out to B,C and D. This can be described in a n-quads file as:

"a" "follows" "b" .
"a" "follows" "c" .
"a" "follows" "d" .

If we bring up the web view using a file with that content we can query:

g.V('a').As('source').Out('follows').As('target').All()

Running it as a query should give you some json:

{
  "result": [
    {
      "id": "b",
      "source": "a",
      "target": "b"
    },
    {
      "id": "c",
      "source": "a",
      "target": "c"
    },
    {
      "id": "d",
      "source": "a",
      "target": "d"
    }
  ]
}

Swap to the graph view, run it again and you should see a graph. Not all that pretty but it’s a start.

Cayley

So what’s happening here? Starting at ‘A’ and calling it “source” we traverse joins named “follows” that go out from A and take note of the end node calling it “target”. Be aware that the source / target is case sensitive and if you get it wrong you won’t see anything. When I say “calling” what I mean is that as the nodes are being traversed it will “emit” the value found with the name provided as the key. This is building up the JSON objects with each traversal as a new object in the returned list.

Doing more

So now we have the basics and that’s as far as a lot of the examples go. Taking things a little further.

I recently read an article 56 Experts reveal 3 beloved front-end development tools and in doing so I came across entry after entry of tools and experts. My first reflex was where are the intersections and which are the outliers.  So I decided to use this as a datasource. I pulled each entry into a spread sheet and then ran a little script over it to produce the quads file with:

"<person>" "website" "<url>" .
"<person>" "uses" "<tool name>" .

and for each first mention of a tool:

"<tool>" "website" "<url>" .

The results was a 272 line quads file with people, the software they used and the urls for the software.

From there I started Cayley with the usual command:

cayley http --dbpath=userreviews.nq

So what next? We can find a product and see who is using it:

g.Emit(g.V('sublime text').In('uses').ToArray())

Which results in:

{
 "result": [
  [
   "stevan Živadinovic",
   "bradley neuberg",
   "sindre sorus",
   "matthew lein",
   "jeff geerling",
   "nathan smith",
   "adham dannaway",
   "cody lindley",
   "josh emerson",
   "remy sharp",
   "daniel howells",
   "wes bos",
   "christian heilmann",
   "rey bango",
   "joe casabona",
   "jenna gengler",
   "ryan olson",
   "rachel nabors",
   "rembrand le compte"
  ]
 ]
}

Note I used the specific emit of the array values to avoid a lengthy hash output.

Sure that’s interesting but how about we build a recommendation engine?

Say you are a user that is a fan of SASS and Sublime Text. What are some other tools experts using these tools like?

// paths that lead to users of the tools
var a = g.V('sass').In('uses')
var b = g.V('sublime text').In('uses')

// Who uses both tools
var c = a.Intersect(b).ToArray()

// What tools are used by all of those people
var software = g.V.apply(this, c).Out('uses').ToArray()

// Convert an array to a hash with counts
var results = {}
_.each(software, function(s){
  if(results[s]==null){ results[s]=0; }
  results[s] +=1;
})

// Remove search terms
delete results['sass']
delete results['sublime text']

// Emit results
g.Emit({tools: results, users: c})

Here we are:

  1. finding the people that use sass and sublime text
  2. finding all the tools they use
  3. counting the number of times a tool appears
  4. removing our search tools
  5. emitting the results as the response

This gives us:

{
 "result": [
  {
   "tools": {
    "angularjs": 1,
    "chrome dev tools": 5,
    "jekyll": 1,
    "jquery": 1
   },
   "users": [
    "bradley neuberg",
    "nathan smith",
    "adham dannaway",
    "wes bos",
    "joe casabona",
    "jenna gengler",
    "ryan olson",
    "rachel nabors"
   ]
  }
 ]
}

Note how Cayley is pretty happy for us to move in and out of JavaScript and that underscore.js is available by default. Handy. Also I returned a custom result construction with both the results hash and the users it was derived from.

So this isn’t necessarily the most efficient way of doing things but it’s pretty easy to follow.

I think for many, the fact that Cayley uses a JavaScript based environment will make it quite accessible compared to the other platforms. I hope to keep exploring Cayley in future articles.

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