Category Archives: Rails

React JS and Rails – real-world results

There are many React JS intros out there, but too few articles about bringing React into an existing Rails app.

At Cook Smarts, we brought React JS into the core of our application, used by thousands of people each week. We moved quickly from the conceptual beauty of React to figuring out how to make it work 100% of the time.

Here’s what React JS delivered in just a bit of time:

  1. A bug-free user experience back to IE 7
  2. Speed, with no detectable latency on the client side
  3. Better structured JavaScript
  4. Thrilled users, who now have a more modern app experience
  5. Developer happiness (that’s me!)

First, some background. Cook Smarts is a service that helps people plan their weekly at-home meals. It suggests meals for the week, and the user can choose which ones to make, add meals from other weeks, adjust serving sizes, and adjust for dietary restrictions.

This is a lot of user interaction. A month ago, users selected which meals to make through a vanilla form. We then generated a static grocery list and meal plan. If they wanted to make any changes, they had to submit the form all over again.

Screen Shot 2014-12-29 at 6.30.05 PM

Screen Shot 2014-12-29 at 6.31.14 PM

It worked, but it needed improvement. Users wanted the app to remember their choices and allow them to check items off the grocery list. They wanted to make their selections as they browsed, not all at once.

We chose React JS because it is un-opinionated and friendly to existing apps. We could drop React into particular parts of the app without changing any other parts.

After implementing React, the meal planning experience is this simple, with no forms:

CookSmartsMealPlanning

React is based on components that you arrange in a tree that basically documents itself. Here are the basic components for grocery list page:

  • GroceryListContainer
    • GroceryListItems
      • GroceryListItem

… and for the menu page:

  • DaysContainer
    • Day
      • DayTitle
      • DayVersion
      • DayServings

With React, you code each component separately, in a mix of JavaScript and HTML called JSX. Your component code contains the layout and behavior of that component, and React makes everything happen on the client.

React has minimal impact on your Rails app’s overall structure, making it easy to bring into an existing app. Here were the basic steps to implementing it:

  1. Add react-rails to your gemfile
  2. Create a directory in app/assets/javascript called “components” and create your components there as .JSX files
  3. Reference your new components in your views
  4. Create the server-side API’s necessary to feed and interact with your React components (this is not React-specific, just something an app needs to do as it implements more client-side functionality)

I presented to a local meetup about the process of implementing React for Cook Smarts, and hope to put together a how-to soon. In the mean time, check out these great resources for incorporating React and Rails:

Feel free to tweet me with any questions!

Update: See a full example of adding React to a Rails app

User announcements for Ruby on Rails with the Starburst gem

If you have an app with users, chances are you need to make announcements to them from time to time.

Starburst allows you to show messages to logged in users within your Rails app. Once the user closes the message, they won’t see it again.

You can target messages to particular groups of users, based on their database attributes or your own methods on the User class. For instance, you might send a message only to users on your premium plan.

Starburst remembers on the server who has closed which message. Therefore, a user who closes a message on their desktop won’t see it again on their mobile device. Starburst doesn’t use cookies, so a user won’t see an announcement they’ve already read if they switch devices or clear their cookies.

Starburst is in production on Cook Smarts, where it has served announcements to thousands of users.

Find out how to install and use Starburst on its GitHub repo, and post an issue there with any feedback!

11 Essential Services for Rails Apps

Developing an app is never a solo effort, even if you are the only developer in a company. We live an ecosystem of services and open source tools that make development more rapid than ever before.

This article covers services and tools that are critical to most modern web applications.

1. Error handling

You need to be aware of any exceptions that occur in your app in production, as they generally indicate bugs.

Honeybadger

Recommended. After you take five minutes to set up Honeybadger, it will alert you to any errors on your app, and allow you to easily browse through each time that error happened. Information with the error will generally tell you who was logged in at the time, so you can provide proactive support to your users.

Airbrake

Airbrake may be the dominant error reporting service, as it just acquired its competitor Exceptional. From my experience, Setup is not as simple as Honeybadger’s, and the interface is so minimal that browsing through the history of an error can be cumbersome.

2. Commerce

Stripe and Braintree offer customers a seamless purchase experience in your app, allowing you to sell one-off items and subscriptions. Both are customizable enough to be transparent to the customer, providing you with full control over the user experience.

Stripe

Recommended. Stripe is extremely developer-friendly on its own, so can be used in quite a custom manner in your Rails app. Unless you use a Stripe partner, you will be writing custom code to interface with Stripe. Stripe Checkout can shave off time off front-end development.

Braintree

Recommended. Unlike Stripe, Braintree offers PayPal integration and phone support. It has matched Stripe’s features including user interface elements that you can plug right in to your app. As of October 2014, Braintree is offering no transaction fees on your first $50,000 of transactions, which could save you around $1,500. Braintree has made Stripe less of a default choice than it was before. Be sure to compare both.

3. E-mail – transactional

Transactional e-mail is specific to a customer. It may include an invoice, an alert about the customer’s account, a summary of the customer’s recent activity, etc. Generally, the contents of a transactional e-mail is different for every customer.

Mandrill

Recommended. From the creators of MailChimp comes an extremely powerful service with generous pricing. Just plug in Mandrill’s SMTP information into Rails ActionMailer, or use Mandrill’s API to send a ton of messages at once. Mandrill offers robust logging, allowing you to see the full contents of recently sent messages. Its deliverability stats demonstrate MailChimp/Mandrill’s excellent record in getting e-mails to people. It is reliable and fast, churning through thousands of messages in just a few minutes (from my experience). Finally, it is free under a certain message limit, and very reasonable thereafter, particularly for MailChimp customers. Many apps will spend just a few bucks a month on Mandrill, if that.

Having transitioned a web app from Sendgrid to Mandrill, it is difficult for me to recommend anything other than Mandrill. Do check out SendGrid and Mailgun, though.

4. E-mail – mailing list

You may want to send all of your users, or particular subsets of them, updates on your service, promotions, and other marketing e-mails.

MailChimp

Recommended. MailChimp has strong libraries for Ruby and other languages lets you add, manipulate, and remove users from your lists easily. You can send custom information about your users, such as which plan they are on, to MailChimp, for targeting purposes.

Customer automation tools

Many apps have needs beyond simple mailing lists. You may want to segment customers based on their behaviors – for instance, reminding a customer to take a certain action if they haven’t already. Check out MailChimp’s newly revamped automation features.

If you need more advanced customer segmentation, check out AWeber and Infusionsoft. Other specialized offerings, like Drip, address niches like e-mail-based courses. With these three tools, be prepared to pay more for a small list than you would with MailChimp.

5. Storage

Generally, you should store static assets, such as your logo, in a separate location from your app. Certainly, you should store any user-submitted images in a separate location.

Amazon S3 + Carrierwave

Recommended. Amazon S3 provides a place to store static assets, such as images and attachments. In the simplest use case, you would manually upload images like your logo, and reference those from your views.

In a more advanced use case, you could allow users to attach images to items in the app, and dynamically upload those images to S3. For that, check out Carrierwave, which makes file uploads to S3 amazingly easy.  Also check out the Paperclip gem.

6. Database

PostgreSQL

Recommended. PostgreSQL is a relational database that enjoys wide adoption among hosting providers like Heroku and EngineYard, and recently introduced highly optimized JSON fields that support more free-form data. It’s a well-maintained, reliable, fast database that should do the trick for most production apps.  Check out how to get started.  If you’re on a Mac dev environment, use Postgres.app to set up a local Postgres server on dev.

MongoDB

MongoDB is a non-relational database suited to more fluid information like documents and “mashups” of data from multiple sources. Some use MongoDB to bring in data from relational database and present it in a different way, since it is so flexible.

Beware, though, that without the rules of a relational database, a MongoDB database is harder to govern, and bulk changes a bear. Consider Mongo if you feel the data you are storing would not be appropriate for a relational database, but be sure to check out Postgres’ new JSON features first.

7. Performance monitoring

New Relic

Recommended. New Relic tells you which methods in your app are running slowly. In many cases, it’s free to use, and you can always upgrade for more granular information. It will alert you to sudden slowness in your app, which is important as you scale. There’s no reason not to get started with a free account for a production app.

App Signal

App Signal, based on Europe, integrates error reporting and performance monitoring in a very clean interface. It’s worth checking out.

8. Code quality

Static analysis checks out your code to find antipatterns, or poor practices could make your app less efficient or more difficult to maintain.

Code Climate

Code Climate quickly finds the poorly-formed or inefficient Ruby and JavaScript code in your app, so you know what to refactor first. Then, it monitors your GitHub repo so you don’t regress.

RuboCop

Prefer to do it yourself rather than use a hosted service? Code Climate likely uses RuboCop for much of its analysis, and you can run it locally for free.

Ruby Science

This isn’t a service, rather a book, but it’s excellent reading that can help you address some of the issues brought up by Code Climate or RuboCop.

9. Authentication

Authentication these days still includes user names and passwords, but is quickly expanding to social sign-in through networks like Google, Facebook, Twitter, and GitHub.

Devise (+ optional Omniauth)

Recommended. The long-time gold standard for authentication in Rails app, Devise pulls its weight as a solution that is quick to implement but also very extendable. It supports user name and password authentication out of the box, and has built-in support for Omniauth to support social sign-in without much pain.

Clearance

Clearance is for people who either, 1.) want very simple user name and password authentication and don’t envision going beyond that, or 2.) want to further control and customize the authentication in their app. Most importantly, it is easier to understand what Clearance is doing because it’s code is lighter. Without turnkey integration with Omniauth, Clearance makes it harder to integration social sign-in.

10. Hosting

EngineYard

Recommended. EngineYard’s support is exceptional, with e-mail and phone available no matter what plan you’re on. You know exactly what you’re getting, because your app and database are hosted on fully-fledged virtual machines with clear specs. You can deploy, manage backups, and spin up/down servers through a simple web interface, never touching the command line.

Heroku

Heroku is conceptually interesting and powers a lot of Rails app. It uses an original concept called “dynos” to allocate your app’s resources and allow you to scale. This abstraction could be helpful, but many might prefer to work with the actual VM’s that EngineYard offers. You’ll most certainly be dealing with the command line, but Heroku’s tools are good.

I’m hesitant about Heroku’s support. You can’t pick up your phone and call them, like you can with EngineYard. Heroku’s default support plan has a “1+ day” response time,  while EngineYard offers a 30 minute response time around the clock for urgent issues. Both services offer enhanced support plans, but EngineYard’s built-in support appears to be better.

11. Backup

If you use a platform-as-a-service provider like Heroku or EngineYard, you’ll generally get backup in the package. Just be sure to use it!

There’s more I haven’t covered here, like continuous integration and deployment. It goes to show that 1500 words don’t do justice to the vast ecosystem available to developers.

Mixed numbers in Ruby / Rails

At Cook Smarts, we’re going to let people scale recipes.

When doubling a recipe, for instance, 1 1/4 cups would become 2 1/2 cups.

These are both mixed numbers, a combination of a whole number and a fraction. We show them to users instead of their fraction equivalents, 5/4 and 5/2.

Rails provides no built-in methods for doing calculations with mixed numbers, so we have to convert them to and from rationals before treating them as numbers.

A rational in Ruby is a number that can be expressed as a fraction. In most cases, all of the quantities in an app can be expressed as rationals.

That way, we can perform calculations and still show users pretty fractions (i.e. 2 1/2 instead of 5/2).

Convert a mixed number to a rational
for calculations

Unlike mixed numbers, rationals can be used in calculations. Use this function to convert a mixed number string into a rational.

Above, we split a mixed number into its integer and fraction components and add them together to form a rational (or whole number). The function can also handle decimals, integers, and regular fractions.

Note: This is not ready for negative mixed numbers.

Convert a rational to a mixed number
for the user

Use this method to convert a rational, like 3/2, into a mixed number that we can show to the user, like 1 1/2.

Above, we convert to a mixed number if the provided number is not an integer and it’s more than 1. Otherwise, we return the number as a string.

A note on precision

Rationals and integers are exact, while decimals and floats are sometimes not. 1/3 is precise, but 1.333333…. is not.

Never mix decimals and fractions if you want to maintain precision.

Creating a Ruby gem for one-time announcements, part 4 – performance, views

I’m developing a gem to deliver one-time announcements to users in Rails apps. See the previous parts of this series for some background.

Now, in part 4, we’ll test performance performance and add a view to show the current announcement.

Measuring performance

How much work does the gem have to do in order to retrieve the latest announcement for the current user?

Database calls are often a performance culprit. Queries should be small in number (see N + 1 problem) and minimally taxing on the database.

The gem runs only one query to retrieve the latest announcement.

To see how long that query lasts, we’ll run the method that calls it in the Rails console. The current method of the Announcement model checks for an announcement for the current user.

What if we have 1,000 announcements and 50,000 users? There are a few ways to test performance of a specific method, one of which is a benchmarking gem from Viget Labs. I used Ruby’s built-in benchmark module.

The call to Announcement still comes in at under 1 ms with 10,000 users and 5,000 announcements.

Showing announcements

A view helper called current_announcement will call the current announcement from the model.

Then, the developer using the gem can pull in the current announcement through a view partial.

We still need to let the user close the announcement, and remember the announcements that each user has read.

Integrating with Foundation and Bootstrap

At Cook Smarts, we use Zurb Foundation, and it’s served us well.

The gem will include templates for announcements using Foundation’s and Bootstrap’s existing styles.

It will also include a template for sites that do not use either framework. In that case, it is up to the developer to style the announcements in the app’s CSS.

What’s next

Next, we’ll talk about remembering which announcements have been read by the current user, security, and how site administrators can add announcements.

Searching across tables with Wice Grid in Rails

Say that in your Rails app’s admin interface you have a table of orders, each of which is associated with a customer. You need to find orders belonging to a particular customer, by e-mail address. This is a search across two tables, orders and customers.

Wice Grid, a fantastic data grid for Rails, makes this search easy. Check out our intro to Wice Grid if you haven’t already, then come back here for this trick.

In your controller, when you declare your grid, include the other table that you’re searching.

Now, in your view, when you define the column that contains the customer’s e-mail address, reference the model (Customer) and the field within that model (email).

Wice generates a search box above the customer e-mail column. Enter an e-mail address to find orders a associated with that customer.

Try out Wice Grid in your Rails app! It makes admin interfaces much easier to build.

For more background, check out our intro to Wice Grid.

If you’re building a broader search feature for your app’s users, check out our intro to full-text search in Rails.

Creating a Ruby gem for one-time announcements, part 3 – targeting messages to users

This is part 3 of building a gem for targeted, one-time announcements to users in Rails. See part 2 and part 1.

We’ll focus on targeting announcements to certain types of users. For instance, the admin may want to deliver an announcement only to users who have subscriptions.

A field in the Announcements table called limit_to_users will specify which types of users should receive the announcement.

limit_to_users can contain multiple conditions, so we’ll make it an array of hashes. ActiveRecord allows objects like these to be stored in text fields in the database, using the serialize method in a model.

This test validates that the field works as intended, storing conditions and allowing them to be retrieved. Here, we are sharing the announcement only with users who do not have a subscription.

Querying serialized fields is tough

It’s risky to query serialized fields in a relational database. MongoDB and similar noSQL databases are tuned for fast queries of free-form information, while Postgres and its SQL siblings are not.

We need to figure out which announcement to serve to which user, even though the conditions are stored in a query-resistant serialized field.

Houston, we’ve got loops

Maybe we should grab all active announcements that the current user has not read, and cycle through them to find the latest one that is relevant to the user.

My first try at this includes two loops, one inside the other, which:

  1. Cycle through each active, unread announcement
  2. For each announcement, cycle through each condition

Loops carry potential performance issues, especially when nested. In this case, we came as far as we could with a query, and used loops for the rest.

The loops do not re-query the database, thus avoiding an n+1 query problem, so they should be pretty quick. We’ll test performance in past 4, coming soon.

Creating a Ruby gem for one-time announcements, part 2 – TDD, marking as read

In part 1, I talked about the need to announce things to users in a Rails app. The announcements should be scheduled, shown to each user only once, and targeted to particular types of users.

We’re building a Ruby gem to enable this.

Tests

I started by writing tests, describing what the one-time announcements gem should do. Test driven development (TDD) can be controversial, but I find that it helps me plan and identify issues earlier in development.

I learned how to test from Everyday Rails Testing with RSpec. The author continually updates it as new versions of Rails and RSpec are released.

The first tests confirm, at the model level, that announcements can be:

  1. Created
  2. Scheduled
  3. Marked as read

These tests pass with the current Announcement model:

Marking announcements as read

Each user should see a particular announcement only once, so I needed a way to mark announcements as read.

The unread_by scope above shows only those announcements which the user has not read. It uses the AnnouncementView model to see who has read which announcements:

The current method chains the ready_for_delivery, unread_by, and in_delivery_order scopes to determine which announcement to deliver.

This StackExchange thread helped, and I took inspiration from a gem specifically for marking messages as read.

What’s next

In part 3, we’ll look at how to target announcements to particular types of users. For instance, what if you have an announcement just for users on a particular subscription plan?

Creating a Ruby gem for one-time announcements – part 1

At Cook Smarts we need a way to provide one-time announcements to customers, right inside our Rails app.

For instance, we may want to notify our paying users of a new feature when they log in.

Once the customer reads the announcement, he or she can close it and will never see it again.

The closest Ruby gem I could find is thoughtbot’s paul_revere. It’s elegant and simple, providing one-off announcements to an app.

It does not, however, support:

  • Start and end dates for an announcement What if an announcement is relevant only for a period of time?
  • Announcements to a subset of users What if an announcement is relevant only to some users?
  • Remembering across devices that a user closed a message If the user already read a message on desktop, why should they see it again on mobile?

What about keeping it simple?

One-off announcements may seem simple at first, but in practice, they benefit from more granularity.

Showing people only the announcements they need, at the right time, and only once, increases the messages’ potency.

Filtering announcements by user characteristics

Each announcement will be filtered based on conditions about the current user. For instance, is the user on a free trial or paid plan? When they did they sign up?

Perhaps we need to grab all announcements the user has not read with a simple database query, and then use some logic to see which of those is relevant to the user.

In any case, I’m looking for a safe, customizable way to target one-time messages.

What’s next

Next, I’ll take you through the process of creating a Ruby gem for one-time announcements. Stay tuned for part 2…

Supporting guest users in a Rails app

Many apps place content behind an account wall. Bringing that wall down and allowing guest users can make content more discoverable and open it up to search engines.

You might often reference the logged in user, to get their first name, for instance. Most authentication gems, like Devise, provide a current_user helper that contains whoever is logged in.

If no one is logged in, however, current_user will trigger an error if you try to a call a method on it. For instance, current_user.first_name would result in an error if no one is logged in.

To get around this, create a guest user class called GuestUser, and give it properties that a real user would have.

Add any other properties that you use with current_user.

Finally, adjust the current_user method to use GuestUser:

If you are using Devise, use this code instead of the previous block to avoid a potential conflict:

Now, you never have to check current_user for nil because it will always equal an actual user or the guest user.

Explore this concept: