Wednesday, 20 May 2015

Rails Active Record .median

Rails neatly provides an .average method to easily find the average value of a column on your db, but it doesn't provide one for finding the median. Thankfully it's really easily to implement

If you just want to add it to one class, put this into the model:

def self.median(column_name)
  median_index = (count / 2)
  # order by the given column and pluck out the value exactly halfway
  order(column_name).offset(median_index).limit(1).pluck(column_name)[0]
end

If you want it to work across all Active Record models in your db... you could add it as a concern (then include it in every class you want it in) or you could just extend ActiveRecord::Base (so it's available to every Active Record, just like .average).

If you want to do that, add the following to /config/initializers/active_record.rb

class ActiveRecord::Base
  def self.median(column_name)
    median_index = (count / 2)
    # order by the given column and pluck out the value exactly halfway
    order(column_name).offset(median_index).limit(1).pluck(column_name)[0]
  end
end

Note: I've tested it even with chained scopes and it seems to work ok on our project (this counts as a final - ie you can't chain after it)

Note: as pointed out to me, the median of an even number of things is the average of the middle two values... and this version doesn't do that - this is a quick-and-dirty version. Feel free to adapt to be mathematically correct if you need that level of precision

Monday, 9 March 2015

Link: Flaws In Scrum And Agile

In The flaws in Scrum and Agile Giles Bowkett explains why Panda Strike feels that Agile is basically a past-technology. Good in it's day, with some useful lessons we can keep, but largely not relevant to the way that distributed teams work these days.

It's a very interesting read, and I find myself agreeing with it.

Monday, 23 February 2015

ActiveAdmin simple_table

ActiveAdmin by default will build you a table (using table_for) for a collection of objects. But sometimes you just want to throw up a quick table of random values - eg on a dashboard you want a table where the left=column is a description and the right column is, say sets of counts of various things.

ActiveAdmin uses Arbre under the covers to build html for you This means you can use it to laboriously build an html table using all the tags. But if you just want to throw together a super-simple table, this means too much typing.

So I've written a convenience method that will take an array of values and convert it directly to a table.

Note: it does no checking... so make sure your array has the same number of columns for each row

# put this in config/initializers/active_admin.rb
module ActiveAdmin
  module Views
    class SimpleTable < Arbre::HTML::Table
      builder_method :simple_table

      def build(collection)
        table do
         collection.each do |row|
           tr do
             row.each do |col|
               if col.is_a? Numeric
                 td col, style: "text-align: right;"
               else
                 td col
               end
             end
           end
         end
        end
      end
    end
  end
end


# example usage
simple_table [ [ "User count", User.count ],
               [ "Item count", Item.count ],
               [ "Total Wishes", Wish.count ],
               [ "Available Items", Item.available.count ] ]