activeadmin-rails

Ten years ago I was a relatively inexperienced Rails consultant hired to accelerate custom development at a rapidly growing e-commerce startup.  A major overhaul was desired for the backend systems using an extensive RDBMS schema and I wanted feedback with a rapid prototype, so I reached for a framework presented at 2011 RailsConf called ActiveAdmin.

Ultimately the overhaul was a success and I was hired to manage maintenance, where I have dug into ActiveAdmin’s features to learn customization, and shared what I learned on the wiki and StackOverflow.  The primary author, Greg Bell, moved on to grander things long ago but others, briefly including myself, stepped up to continue maintenance of the gem from Rails 3 through the present.

In some ways ActiveAdmin in 2011 was ahead of its time, the UI built from the ground up using HTML views in Ruby extracted as Arbre (similar to Markaby, Erector, Fortitude and now Phlex).  For better or worse this approach  failed to make in-roads against Erubi and Haml/Slim templates, then a few years ago ES6 revitalized front-end development and gave rise to React, threatening to delegate Rails to an API only framework.  Fortunately Rails has now evolved with Hotwire and Stimulus, and GitHub has pioneered a new Rails compatible framework called ViewComponent.

In other ways ActiveAdmin in 2011 was a product of its time, leaning heavily on Ruby meta-programming to build an extensive configuration DSL.  While impressive in some respects it also adds to the learning curve for both advanced customization and trouble shooting.  Since then mainstream Ruby development has swung back to a more object oriented approach emphasizing inheritance and composition: Administrate exemplified this trend and was a real eye opener to me when it was announced.

Where does that leave ActiveAdmin in 2023?  Many have already moved on to the likes of react-admin, but in my opinion Rails 7 is time for a significant overhaul, and this fork is my effort to offer an alternative with a clear migration path.

Year Thirteen with Rails

These last twelve months have been the first without a major or minor Rails release, though there have been multiple bug-fix patches to 7.0. Ruby 3.2 included production ready YJIT and better ReDoS protection. InfoWorld published ‘Whatever happened to Ruby?’ However, the biggest buzz has been figuring out how to use ChatGPT productively: a much easier task with greenfield projects I think.

At my employer the focus has been on Google Ads, fraud detection and logistics improvements.
Nonetheless ‘maintenance mode’ still includes an unending flow of diverse fixes and refinements such as unearthing race conditions and fixing transaction boundaries. 3DS v1 was sunset, AWS abandoned Data Pipeline, and we explored Terraform. Apollo GraphQL has been retired as REST based alternatives are holding up good enough.

New gems used this year included `validates_email_format_of` and integrations with Braintree and AfterShip.

On StackOverflow I drifted into the ‘activeadmin’ tag top 15

For better or worse my only open source contributions have been to my own evolving fork of ActiveAdmin: using a different rendering strategy for Arbre, embracing Rails layouts, slashing controller meta-programming, and reducing dependency on the resource DSL.

Year Eleven with Rails

Five years after our adoption of React on Rails this year has seen the release of Stimulus-Reflex and the refinement and extension of Turbolinks and Stimulus into Hotwire, a welcome, mostly server side alternative.  So far we have only explored Frames for faster TTFB but we’re optimistic about wider applications.  Also notable this year Rails 6.1 shipped with built in support for ViewComponents, though we are yet to complete our upgrade or move from Ruby 2.7 to 3.0.
At my employer our modular monolith architecture remains unchanged. Interestingly Shopify published a nuanced engineering article concluding “all large architecture changes end up in an incomplete state”.  Apart from European PSD2 mandates, a new billing strategy and greater Facebook marketing API integration, our focus has been on improved change logging and auditing, and tidying and extending test data factories, VCR cassettes, interactor, job, request and feature  specs.  Along the way we refactored offer management, logistics exports, PayPal Express Checkout and fraud detection.  For the first time this year no new gem dependencies were introduced, though we forked PayPal’s REST SDK, abandoned by PayPal.
After years answering 160+ ActiveAdmin questions on StackOverflow I reached the top 20 contributor list and earned StackOverflow’s ‘activeadmin’ badge… time to retire, I think.

Active Admin monthly downloads nearly doubled last year

According to this blog post Active Admin monthly downloads nearly doubled last year to almost 3,000 times a day.  Part of that can probably be attributed to increasing use of continuous integration, but more interesting is that Active Admin has outpaced the competition. Possible contributing factors include three releases, including a 1.0 release that coincided with RailsConf and was featured by Ruby Weekly, a GoRails episode by Chris Oliver at the end of 2016, and the blog post by Charlie Gleason on using Active Admin as a back end to a React application, that has been discovered and tweeted by new fans repeatedly. I’ld love to think that timely responses to GitHub issues and pull requests and StackOverflow answers have helped also, along with the curated wiki and continuing contributions by plugin authors. Also there have been Japanese blog posts and activity so more adoption there. At this point Active Admin has 7,800 GitHub stars and 2.9M downloads, it will interesting to see how things are another year from now.

Arbre vs React

Arbre is a component based server side DOM rendering library written in Ruby.  Arbre was extracted from Active Admin from 2011-2012  but has not gained widespread use elsewhere.  As of September 2017 there were around 4M downloads to date from RubyGems and barely 450 stars on GitHub.

class Panel < Arbre::Component
  builder_method :panel

  def build(title, attributes = {})
    super(attributes)

    h3(title, class: "panel-title")
  end
end

React is a component based isomorphic DOM rendering library written in Javascript.  npm downloads have reached 40M in the past couple of years and the project has 75,000 stars on GitHub: it’s no contest really.  If you prefer Ruby over ES6 an Opal wrapper is available as hyper-react .

class App < Hyperloop::Component
  render(DIV) do 
    MainNavigation {} 
    PageContents {} 
    Footer {} 
  end
end

The APIs for both are relatively simple.

Arbre has builder_method to register components.  Each component has a build method which adds tags to an Arbre::Context that is eventually output using to_s.

React components have a render method that adds elements to a virtual DOM that is synchronized with the browser DOM as needed.

The most obvious difference is that Arbre does not integrate Javascript event handlers: it uses an unobtrusive approach that leaves registering event handlers to accompanying ES6/Coffeescript/Opal files.

Being exclusively server-side means that Arbre can and has been used with ActionView helpers and templates.  There are bugs but it mostly works.  Arbre is relatively simple and provides what Active Admin needs without further dependencies.

React components are careful about maintaining state and re-render when state is changed.  Arbre components get re-instantiated for each request and are more ad hoc.

Is anything to be learned from this comparison?  The prospects of widespread adoption of Arbre are slim to none.  An increasing number of developers are going to be looking to use a Rails admin framework with React, and that is where opportunity lies.

Year 7 with Rails

In my seventh year with Rails I started allocating ’20% time’ to maintenance of Active Admin and related open source gems.  As the universe of web technologies continues to expand and fragment there has been increasing acknowledgement at GitHub and elsewhere of the stresses on volunteer contributors and the consequent rise in the number of projects falling into disrepair.  Active Admin at least now has an official 1.0 release and timely support for Rails 5.1.
On the plus side competition and the exodus from Rails has brought back innovation, most notably Rails 5.1’s integration of NPM, Yarn and Webpack.  Beyond Rails in the wider Ruby community an object-functional style of programming is gaining popularity, championed by dry-rb and embraced by Hanami and Trailblazer.
This year has been one of considerable progress (and hype) around containers and microservices.  Microservices are not without tradeoffs but Docker containers have proven themselves useful in both development/CI and production.
At my employer our codebase has reached 50kloc, now 60% componetized into gems, but a new joint venture has doubled our infrastructure and provided incentive to switch to Docker (and Elastic Beanstalk).  Containerizing legacy applications is not always trivial, however, as adopting a 12-factor approach means simplifying and standardizing sometimes disparate logging and configuration solutions, as well as changing to process supervision in a stripped down POSIX environment instead of a full blown Linux host.  Our monitoring stack now includes Pingdom, Airbrake, Loggly, PagerDuty, Skylight, (CloudWatch) and Librato.  Moving CI to Docker has been challenging, with initially only CodeShip providing a SaaS solution with parallel tests each with multiple sets of containers.
Looking forward Rubyconf last November continued to raise hopes that performance and concurrency will be improved… eventually.  Meanwhile there are numerous projects working on integration with compiled languages: helix with Rust, swig with C/C++, Loren Segal’s gorb with Go, and rubex.  Crystal has gained attention as a Ruby-ish experiment on LLVM with its own MVC frameworks.
On the front end React may now be a ‘safe’ choice for front end development but possibly disruptive innovation continues with VueJS, CycleJS and Elm.  The next twelve months will see either our further adoption of React on Rails or a shift to a different approach.

Active Admin 1.0

Note: This post is by Varyonic, not the ActiveAdmin organization.

So after nearly seven years Active Admin 1.0 is out. It has been a long and sometimes uncertain journey of which I have witnessed only part. The original author has moved on, subsequent maintainers have burned out, changed jobs, started families… The bug list remains longer than we would like, the features list remains longer than we can handle, but Active Admin has been in production use for years at companies, NGOs and agencies, and there is commitment to keeping the project alive through quiet pragmatism rather than grand plans.

Not all of us have the time, money, or even need for the next shiny thing, and even if Active Admin sometimes cuts across ‘the Rails Way’ it can be a significantly productive tool. I encourage you to give it a try, to upgrade if you are already using it, to give us feedback if you find issues. General help is available on StackOverflow (tag #activeadmin); search the GitHub issues, both open and closed (~5,000 in total), before submitting anything new. If you are using Active Admin regularly consider looking through the code, issues and the commit log, maybe you will be inspired to contribute, even if just documentation or translations. If you are working for an agency with multiple customers you may be able to provide valuable insight and encourage adoption.

So thank you to all 500+ contributors so far and especially Timo for the past couple of years, here’s to the next 1M downloads.

From Rails 3.2 to Rails 4.2 If We Really Must

Rails 5 is almost upon us and we’ve spent the last two months, amongst other things, moving our 45,000 lines of Rails e-commerce code from 3.2 to 4.2. For better or worse the move has been less about embracing new features and more about compliance and maintaining security bug fix support. The move has been a rapid succession of stages, from 3.2 to 4.0 in development, 4.1 in production, and finally 4.2 in production. Overall it has been a significant effort and a learning experience.

The biggest challenge we encountered was not fixing our 175 models and 40 controllers, but dealing with our nearly 100 open source gem dependencies. The project started from a proof of concept elegantly scaffolded with ActiveAdmin’s DSL and has accreted functionality and third party interfaces for the past four years. ActiveAdmin remains the leading Rails admin interface, but with the departure of Greg Bell momentum has slowed. Sean Linsley, Timo Schilling and others have put a significant amount of effort into answering questions and applying bug fixes, but the ambitious 1.0 milestone has remained unmet for two years, and gem releases have been infrequent. To update ActiveAdmin first we switched from stable 0.6 gems to the master branch in GitHub, replacing meta-search with ransack, then we worked our way down the master branch to 1.0.0.pre1 in 90 day increments, isolating and working around the issues that impacted us (#2233, #2679, #2771, #3038/#3324, #3145, #3147, #3486, #3591, #3776, #3784). Critical to this effort was our test suite coverage, which remains a disappointing, but so far adequate, 90% (and yes, we upgraded to RSpec 3.x as well).

Apart from gem dependencies the most dramatic issue updating Rails was the breakage of non-strict mode used with our old MySQL database (and thus nearly everything). For Rails 4 we needed to configure ‘strict: false’ to ignore our true mode setting in the database, then with Rails 4.2 this changed again and we needed to explicitly set variable sql_mode to the required value.

So what has Rails 4.x brought us? ActiveRecord foreign keys and enums, but we embraced the foreigner and enumerize gems long ago. Spring, but we so loved Zeus. secrets.yml but we already use environment variables and dotenv. Web Console, but we are happy with Better Errors and Pry. An improved cookie serializer that fouled up our ‘seamless’ rolling production upgrade. Autoloader vexation. Millisecond DateTime rounding errors (or is that due to OS X?). ActionMailer::Preview and ActionMailer#deliver_later, but we have already built out more sophisticated solutions. Strong parameters for sure. New bin/ scripts. Stricter routing with Patch. An end to ActiveRecord’s old dynamic finder API and tweaks to callbacks and ActiveRecord::Relation. Better performance, please, from Aaron’s AdequateRecord. ActiveJob as a wrapper for Resque or Sidekiq. ActiveSupport::Testing::TimeHelpers. Perhaps for us most importantly a step closer to greater concurrency with Puma (and LiveStreaming?), Sidekiq, Celluloid, who knows?

More detailed ActiveAdmin update notes

Scroll to top