Sinscary Sinscary - 3 months ago 10
Ruby Question

Show models where Rails engine's model are enabled

So i am working on a rails engine, which have

upload
and
validate
functions. once file is uploaded a user will click on validate and than it will save the data from excel file to app's table. My engine won't provide any migration, all migrations will be provided by the app.

Now when i mount my engine, my engine's model are needed to be registered in some of app's model. For e.g. if there are total 10 models and my engine's model are registered only in 3 models of app than it should show me on which models of app my engine's model are enabled.

Than also i should be able to access tables for those models in my engine to save data from excel file.

code for engine's model is

require "roo"

module MyEngine
class Upload < ActiveRecord::Base
self.table_name = "admins"

def self.validate(file)
spreadsheet = open_excel(file)
header = spreadsheet.row(1)
for i in 2..spreadsheet.last_row do
row = Hash[[header, spreadsheet.row(i)].transpose]
upload = Upload.new(row)
upload.save!
end
end

private

def self.open_excel(file)
case File.extname(file)
when ".xls", ".xlsx" then Roo::Spreadsheet.open file
else raise "File format not supported"
end
end
end
end


Here as you can see that i have hardcoded to set the table name but its not possible to set table name everytime.
Any help would be appreciated. I am really frustrated and tired as i have been stuck on this problem from last two weeks. I am new to ruby and its first time for me when i am writing a engine.

Answer

To have a some sort of communication between the engine and the hosting app models, many gems (aka engine gems) follow the ActAsSomething patern.

Here is an example just to point you to the direction (untested code):

require "roo"

module MyEngine
  module Uploadify
    extend ActiveSupport::Concern

    module ClassMethods

    def acts_as_uploadifiable(options = {})

      #you can use a passed hash to control matching attribute names
      # acts_as_uploadifiable attributes: [attr1, attr2, ... etc]

      # to evaluate on model who called acts_as_uploadifiable
      class_eval do
        def self.validate(file)
          spreadsheet = open_excel(file)
          header = spreadsheet.row(1)
          for i in 2..spreadsheet.last_row do
            row = Hash[[header, spreadsheet.row(i)].transpose]
            #not sure what you want to do here!
            upload = Upload.new(row)
            upload.save!
          end
        end

        private
          def self.open_excel(file)
            case File.extname(file)
            when ".xls", ".xlsx" then Roo::Spreadsheet.open file
            else raise "File format not supported"
            end
          end
      end
    end
  end
end
# make Uploadify module avaiable to all our models
ActiveRecord::Base.send :include, MyEngine::Uploadify

I've found browsing other gems source code to be the best way to learn how to write engines. Goodluck!