Posts tagged ‘open source

Natural Resource: Avoiding ActiveAdmin


Natural Resource was born from frustrations experienced on legacy projects that used gems like ActiveAdmin to provide an admin interface for an app. For the very basics ActiveAdmin is great; it provides you a set of functionality out of the box that you don’t have to implement yourself.

Unfortunately, we are all aware that requirements change and functionality grows. ActiveAdmin forces you to extend it using its own concepts outside of standard Rails practices, sometimes going so far as to mix routing, controller and view details in the same file.

Rolling your own admin functionality?

After a frustrating few hours grappling with AA’s quirks, it’s easy to understand why someone would resort to rolling their own admin interface. Advanced admin features shouldn’t be any harder to implement than the rest of your app.

Secondly, it’s often hard to integrate large, opinionated admin gems because they try to blend authentication and/or authorisation logic with their own concepts. Whilst Natural Resource is also opinionated, it exists and performs in a very simple way and is easily overridden.

Enough talk - show me the code!

The following is a typical NR-based controller:

# Controller for generating and displaying Reports for orders received
class Admin::OrdersController < ApplicationController
  include AdminController
  include ReportDownloading

  resource :order

  def resource_scope
    Order.includes(:txns, line_items: [:product])

  def report_class

If we take the above to have authenticated our admin-user (via your own AdminController concern) then our view could look like this:

%h1 Order Report

= search_form_for [current_context, query] do |f|
  = f.input :user_email_cont, label: 'Recipient Email'
  = f.input :amount_cents_gt, label: 'Amount greater than'
  = f.button :submit, "Apply filters"
  = link_to 'Download report', [:download, current_context, :orders,
    q: params[:q])

    %th Order Reference
    %th Payment Method
    %th Recipient Name
    %th Amount
    %th Created At
  - resources.each do |resource|
      %td= resource.reference
      %td= resource.source_type.titleize
      %td= resource.amount.format
      %td= resource.created_at

= will_paginate resources

The above controller offers several helper methods:

  • current_context is a method defined to specify the area of the site you are in. It is used for consistently defining routes.
  • query is the Ransack search object used for defining simple querying using the Ransack syntax.
  • resource_scope is the initial scope of the objects scoped via its respective policy, i.e. policy_scope(resource_scope)
  • resources is the lazy-loaded, paginated result of applying the Ransack query across the resource_scope method.

In Summary

The main motivation behind Natural Resource is to be pragmatic. There are further extensions that can be made to it to allow auto-generating initial views if a sensible standard set can be decided upon without introducing too much overhead/complexity.

It provides a rich set of foundational functionality and tries its best to take a sensible modular, easily overridden approach to standardised components.

There is an NR example repo that contains a more detailed example, but nothing beats reading the source. The majority of functionality is only ~100 lines long. I will add to the NR example repository as we use NR at Terracoding, converting the git history to a series of steps you can follow in the README.

Dynamic Rails App Theming

Themer UI

We started work on an exciting new project this week that requires a single Rails app to power multiple similar websites. The websites are all going to have the same features and basic structure but the client wanted to be able to customise colours, fonts and images for each site themselves.

To get our heads around the feature, we built a prototype app that provides a theme editing interface. You can try out the demo!

Themer UI

Technical Details

You include theme style rules in special comment blocks using color(), font(), and image_url() helpers:

body {
  /* defaults */
  background: white;
  color: black;
  font-family: sans-serif;

  /* THEME --------
  background-image: image_url(bg);
  color: color(text);
  font-family: font(body);
  -------- THEME */

Running rake theme:update will then generate a theme template from those comments at app/views/themes/show.css.erb.

Theme attributes can be easily added to the Theme model. The controller :show action is cached and the generated stylesheet is available at /theme.css to be included in the head of any page.

The theme editor presents a live preview by injecting styles into an iframe as the theme values are changed. This includes images, using the FileReader API to read them locally in Base64 before they are uploaded to the server.

To make sure override rules with missing values degrade gracefully, the app utilises browsers’ behaviour of ignoring any invalid rules whilst continuing to render the rest of the styles. This means any default styling can simply be included in the app’s main stylesheet (or anywhere you like).

Open Source

All of the source code is available on GitHub. Please fork and reuse the code as much as you like! Feel free to open an Issue on GitHub or you can reach us on Twitter @terracoding.

Post Archive