4

I'm in the process of writing a Rails engine that requires some setup config and also does a check to see if some required attributes are defined on a model. The engine class in lib that defines this is as follows.

module Kiosk

  mattr_accessor :kiosk_class
  @@kiosk_class = 'Computer'

  mattr_accessor :kiosk_primary_key
  @@kiosk_primary_key = 'id'

  mattr_accessor :kiosk_type_foreign_key
  @@kiosk_type_foreign_key = 'kiosk_type_id'

  mattr_accessor :kiosk_name_attribute
  @@kiosk_name_attribute = 'name'

  mattr_accessor :kiosk_ip_address_attribute
  @@kiosk_ip_address_attribute = 'ip_address'

  mattr_accessor :kiosk_mac_address_attribute
  @@kiosk_mac_address_attribute = 'mac_address'

  # Private config and methods

  def self.setup
    if block_given?
      yield self
    end

    check_fields!
  end

  def self.required_fields
    [@@kiosk_primary_key, @@kiosk_name_attribute, @@kiosk_ip_address_attribute, @@kiosk_mac_address_attribute, @@kiosk_type_foreign_key]
  end

  def self.check_fields!
    failed_attributes = []
    instance = @@kiosk_class.constantize.new

    required_fields.each do |field|
      failed_attributes << field unless instance.respond_to?(field)
    end

    if failed_attributes.any?
      raise "Missing required attributes in #{@@kiosk_class} model: #{failed_attributes.join(', ')}"
    end
  end

  def self.klass
    @@kiosk_class.constantize
  end

end

The model name and attribute names can be configured in a required initializer that does the job of calling setup passing a block of config parameters. That is,

Kiosk.setup do |config|

  # The name of the class that stores info about the kiosks
  # It should contain the required fields whose names are defined below
  # config.kiosk_class = 'Computer'

  # The primary key of the kiosk class
  # config.kiosk_primary_key = 'id'

  # A foreign key in the kiosk class for the kiosk type
  # config.kiosk_type_foreign_key = 'kiosk_type_id'

  # An attribute containing the name of the kiosk
  # config.kiosk_name_attribute = 'name'

  # An attribute containing the IP address of the kiosk
  # config.kiosk_ip_address_attribute = 'ip_address'

  # An attribute containing the MAC address of the kiosk
  # config.kiosk_mac_address_attribute = 'mac_address'

end

The problem that I encountered during testing is that if a required attribute is missing then calling any generator or Rake task also fails meaning the attribute cannot even be added.

What I would like is to be able to detect in my setup whether it is being called as part of the server start (and therefore should do the fields check) or as any other Rails startup such as Rake tasks, generators, etc. (and therefore should skip the fields check). I feel there must be a solution because starting the Rails console never fails.

Alternatively, if this is not possible, how would you perform the fields check outside of the initializer but in a way that is guaranteed to occur during server startup and only have it happen once per startup?

I realise that similar questions have been asked before on knowing what context an app is running under (e.g. How to prevent initializers from running when running `rails generate` and Rails 3 initializers that run only on `rails server` and not `rails generate`, etc) but the solutions presented there are not very useful for my situation.

Community
  • 1
  • 1
richard
  • 1,565
  • 2
  • 18
  • 35
  • How do you load this module? – Mike Szyndel Jul 11 '13 at 06:23
  • Since the module is part of the engine, it is automatically loaded by Rails when it loads the engine as far as I understand it. That is, my engine is called `Kiosk` and this file (called kiosk.rb) is stored in the `lib` folder of the engine. – richard Jul 15 '13 at 02:06
  • But what's the point of it? – Mike Szyndel Jul 15 '13 at 07:22
  • Possible duplicate of [Rails 3 initializers that run only on \`rails server\` and not \`rails generate\`, etc](http://stackoverflow.com/questions/8660019/rails-3-initializers-that-run-only-on-rails-server-and-not-rails-generate-e) – davmac Feb 17 '17 at 12:05

0 Answers0