Personal website of Martin Tournoij (“arp242”); writing about programming (CV) and various other things.

Working on GoatCounter and moreGitHub Sponsors.

Contact at martin@arp242.net or GitHub.

This page's author

FlagShihTzu & Formtastic don’t work together out-of-the-box, but this can be solved with a few lines of code.

There are a few ways to do this; here’s mine:

class Spaceship < ActiveRecord::Base
    has_flags(
        1 => :warpdrive,
        2 => :shields,
        3 => :electrolytes,
        column: 'features',
    )

    # Allow easy assignment from formtastic as an Array; for example:
    # ['', '1', '', '3'] will set features to 4 (:warpdrive
    # and :electrolytes)
    def features_array= val
        self.features =
            if val.respond_to?(:reduce)
                val.reduce(0) { |memo, n| memo + n.to_i }
            else
                val
            end
    end

    # Get as an Array with all bits set as an int, ie:
    # [1, 3]
    # This allows easy use in formtastic
    def features_array
        features.to_s(2).split('').reverse
            .map.with_index { |bit, i| 2 ** i if bit == '1' }
            .compact
    end
end

Now you can do this in your view:

= f.input :features_array, as: :check_boxes,
    label: I18n.t('Which features does your spaceship have?'),
    collection: flag_to_collection(Spaceship, 'features')

And you may also want this little helper:

def flag_to_collection model, col
    model::flag_mapping[col.to_s].map do |k, v|
        [I18n.t(k, scope: "activerecord.attributes.#{model.to_s.tableize.singularize}.#{col.pluralize}"), v]
    end
end

P.S. Don’t forget to add :features_array to the StrongParameters if you’re using Rails 4.