Stuck? Need startup advice?

Translating attributes on a custom ActiveModel class

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on February 24, 2015 with comments

With an ActiveRecord model, you can add translations for your attributes in a translation file. For example we keep a file app/config/locales/activerecord.nl.yml in one of our applications:

nl:
  activerecord:
    attributes:
      post:
        title: Titel
        author: Auteur

Now, how would you translate the attributes for a database-less model? For example, for validating an email contact form:

class ContactRequest
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming
  extend ActiveModel::Translation

  attr_accessor :from, :message

  validates :from, presence: true

  def initialize(to: nil, message: nil)
    @from = from
    @message = message
  end
end

It's easy: Just add an activemodel namespace in your translation file instead of activerecord:

nl:
  activemodel:
    attributes:
      contact_request:
        from: Van
        message: Bericht

Let me know if this works for you!

Crap. We now have a code style guide.

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on August 11, 2014 with comments

Why didn't we have one? To be honest, I have never given it much thought. I know most of the teams I know have adopted a style guide. But, I never experienced that writing and reading code for our apps was a problem. My approach has always been "common sense > following rules" especially when following rules takes a lot more time. My approach has never included the need for a style guide.

So what changed? We're adding a few people to our team. The current approach is something that my brains like, but that doesn't mean other brains do too. My job is to ensure that all of us can make changes to our development process and make it better. If that change is a style guide, we go with that.

We've had a bit of discussion, and there are a couple of reasons why we think adopting a style guide will help us:

  • Your brains don't have to switch between reading separate variations of style. And this saves brain cycles.
  • Someone who's new on the project doesn't have to worry about how to write code. It's much better when you can just jump in, be productive and ask questions about architecture and design decisions instead of focusing on spaces and comma's. And this saves brain cycles.
  • Pull Request reviews will focus on the high level, instead of comma's and spaces. This is because we'll be using HoundCI for reviewing code style in our Pull Requests, so we don't have to do that ourselves. And this saves brain cycles.

After a bit of discussion, we picked Thoughtbot's style guide, mainly because it's the default in HoundCI. We also looked at bbatsov/ruby-style-guide. We agreed that it didn't matter which style guide we would pick so long as we stuck with it. We did have some discussion about the preference of using double quotes over single quotes everywhere. We also dropped the max 80 characters line limit.

I am glad about our choice. Especially since we only had a (very!) short discussion on Campfire about it, and everyone agreed with the final decision. There will always be personal preferences and discussion on changing our code style might arise from time to time. I think that that's perfectly fine and in moments like those I'll try to remember that having common sense is always better than following rules.

Be a beginner at something, everyday

4df0809f99c19f7b5e0e673836262106?size=150
by Bob Jansen on April 11, 2014 with comments

This week I worked on my first Wordpress blog theme. And it was a lot of fun. I put on my training wheels and set off into the unknown, excited. Compared to my normal development speed progress was dead-slow. But with every line of code and every search in the Wordpress code documentation I was learning. Which was great.

Doing a project like this from time to time is really important. Economically it might not be the best investment of time. I could've hired a good Wordpress freelance developer on oDesk to do the same work in a fraction of time. But doing this myself was emotionally rewarding.

Trying something new allows you to do stupid things. Things that would've been done by experienced people. But that's precisely the point. It's a reminder that you correct yourself. Spot things that don't make sense or could've been done better and more easily. You learn to collaborate and ask questions and process the answers.

Simulating external services during design and development

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on January 21, 2014 with comments

I'm working on an application that uses an external service to generate quotes for an order. When someone places an order, the external service generates a PDF that we save to our database. One problem is that the external service only works when I log into it and take manual action to generate a quote. This is an inconvenience when designing the interface and testing our application's end-to-end flow for other developers and designers. So, I decided to write some code to simulate communication with the external service when developing. This way we make designing, demo-ing and testing with the external service easier.

How do I simulate the external service?

I have one Sidekiq job that sends an order to the external service and saves a quote PDF on my model. This looks like this:

class SendQuoteRequestWorker
  include Sidekiq::Worker

  def perform(order_id)
    order = Order.find(order_id)

    connection = Faraday.new(url: Rails.configuration.x.quote_service.url)
    get_quote_response = connection.post "/quotes"

    quote_info = JSON.parse(get_quote_response)
    order.quote_id = quote_info['quote_id']
    order.quote = StringIO.new(quote_info['quote_pdf']))
    order.save

    NotificationMailer.notify_user_of_quote_created(order)
  end
end

In development, I do not want Faraday to send a HTTP request to the external service. I want to fake this behavior and save a quote from a fixture. This way my team members that do not have access to the external service, can still test our application's flow of requesting a quote and continue with designing the interface.

To do this, I added a configuration option called Rails.configuration.x.quote_service.simulate using the custom_configuration gem by @dhh and modified the SendQuoteRequestWorker Sidekiq worker to use this configuration option:

class SendQuoteRequestWorker
  include Sidekiq::Worker

  def perform(order_id)
        if Rails.configuration.x.quote_service.simulate
      perform_simulate(order_id)
    else
      perform_real(order_id)
    end
  end

  def perform_simulate(order_id)
    order = Order.find(order_id)
    order.quote_id = SecureRandom.uuid
    order.quote = File.open(Rails.root.join('test', 'fixtures', 'files', 'quote.pdf'), "wb")
    order.save

    NotificationMailer.notify_user_of_quote_created(order)
  end

  def perform_real(order_id)
    order = Order.find(order_id)

    connection = Faraday.new(url: Rails.configuration.x.quote_service.url)
    get_quote_response = connection.post "/quotes"

    quote_info = JSON.parse(get_quote_response)
    order.quote_id = quote_info['quote_id']
    order.quote = StringIO.new(quote_info['quote_pdf']))
    order.save

    NotificationMailer.notify_user_of_quote_created(order)
  end
end

My controller code doesn't have to change:

class OrdersController

    def create
      order = Order.new(order_attributes)
      if order.save
          SendQuoteRequestWorker.perform_async(order.id)
          redirect_to finished_order_url(order)
      else
          render :new
      end
  end
end

There is one case that I need to solve. When implementing the external service, I want to be able to test the communication while developing. So, in config/environments/development.rb I added a line to set the Rails.configuration.x.quote_service.simulate from an environment variable that I can set in my .powrc locally.

So, in config/environments/development.rb:

OrderApp::Application.configure do
  # other configs

  config.x.quote_service.simulate = (ENV['QUOTE_SERVICE_SIMULATE'] == 'true') || true
end

Now, if I want to disable simulation in development, I set my .powrc to:

export QUOTE_SERVICE_SIMULATE=false

And restart pow. This will start my Rails app with the QUOTE_SERVICE_SIMULATE set to false and my app will execute the real code that communicaties with my external service.

Conclusion

Simulating the part of the job that connects to the external service, makes designing and developing our application easier. With the configuration option in development.rb, I can enable the real code to be executed when working on the implementation with the external service.

Backups I dream about

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on January 03, 2014 with comments

I dream about good backups.

  • Backups should be encrypted
  • Backups should be pulled from your servers, not written to another server
  • Backups should be stored somewhere safe, where the right people can access it

I've written down some thoughts about the difficulties with backing up:

Why are backups this hard

Making backups is hard to do securely and with confidence that everything is humming along smoothly when your cronjobs kick in at night.

Read the rest of this article →

Intercity Preview: Installing a server to run Ruby on Rails

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on December 30, 2013 with comments

Intercity is our new server management application. It makes you and your team a better Ruby on Rails company by making server management easy. In this preview I'll show you how easy it is to install a server to run your Ruby on Rails applications.

Intercity saves you the hassle of setting up a server by installing your server for you. It installs the nginx web server, and creates databases and configuration files for hosting Rails apps on your server. And it uses random generated passwords and best deployment practices from the Ruby on Rails community.

I will now walk you through the steps of installing a server with Intercity.

Read the rest of this article →

Creating fancy money entry for your Rails app

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on November 21, 2013 with comments

This week I was working on a client project where we wanted to implement a nice way of entering an amount of money. We wanted to replace a standard text input field with something like this:

Money entry sample

In the resulting implementation, when the user types the amount in the text box it automatically splits thousands and the decimal point.

Here's how this is implemented in Rails:

Read the rest of this article →

Testing your own API classes without mocking, Part 1.

Fb613ae74d247c05eba250f575e2c9b0?size=150
by Michiel Sikkes on November 12, 2013 with comments

Recently, I had to hook up a Ruby on Rails app to a SAP Business One installation. This involved doing things like connecting to a SOAP web service. Multiple points in my application had to make use of this connection, so I decided to write a separate class for it. Here is a simplified version:

Read the rest of this article →

The Hidden Job of the M7 processor in the iPhone 5s

4df0809f99c19f7b5e0e673836262106?size=150
by Bob Jansen on November 05, 2013 with comments

Apple launched the iPhone 5s a couple of weeks ago. The 's' line in the iPhone range is known for it's spec bumps and minor updates. This year however the iPhone got two distinct features that improve the usability of the phone on many levels. TouchID helps you log-in to your phone using your fingerprint. The M7 processor contains all the hardware for tracking purposes.

Read the rest of this article →

Steve Jobs explained Customer Development pretty well

4df0809f99c19f7b5e0e673836262106?size=150
by Bob Jansen on November 04, 2013 with comments

Steve Jobs quote on Customer Development

One of the biggest mistakes made in startups is asking people what they want. It's not uncommon I see startups only testing their products and services. While instead they should have been asking and researching the problems.

Your target audience is under constant influence. By the time you finally ship the working product someone asked for, their view on what they want has changed. Probably already found an alternative or solved the problems themselves.

Secondly people are really bad at predicting their own behavior. They know about their problems, but they can't design the best solutions. They have ideas, but probably those are not suited for the mass market.

Designing working and marketable solutions for problems is your job. Not that of the people you talk to.

How the product is perceived is what you should measure when the product is being designed. But measuring how people like a solution is very different than asking how they want their problems solved.

Update: Check out this post from VentureHacks for a more in-depth look how Steve applied Customer Development.