PLUGIN DEVELOPEMENT CENTER

Introduction

Third party plugins can be added to Fedena if new custom features are to be made, which is not distributed with Fedena if required, but care should be taken not to mess up the fedena as well as to maintain the state of plugin during updates. No files of fedena should be modified since every changes made to the core files will be discarded and the files will be updated to the latest version. Similarly modifying the existing databases of the table is also not advisable. Certain guidelines have to be kept in mind while developing a custom plugin for Fedena.

Creating Plugins

Location

Plugins for fedena are placed in 'vendor/plugins/' folder inside the Fedena installed folder.

Naming the plugin

It is highly recommended to prefix the plugin name with any suitable prefixes like name of the company, institution name etc. For example, if we need to create a plugin with the name 'test_plugin' we shall name it 'foradian_test_plugin'. It is also recommended not to use the prefix 'fedena'. These conventions are to ensure that the custom developed plugin will not create conflicts with the working of Fedena core module and plugins bundled with fedena, or doesn't get replaced. No files that are part of the Fedena package should be modified as they will be restored to original state during the application update.

Generating the plugin

All the basic types of files in its required folder structure can be generated by entering the command 'script/generate plugin' in terminal or console from the directory where Fedena is installed.

If we want to create a plugin called 'foradian_test_plugin', we start by the command

script/generate plugin foradian_test_plugin

This command outputs the following lines in the console.

create vendor/plugins/foradian_test_plugin/lib
create vendor/plugins/foradian_test_plugin/tasks
create vendor/plugins/foradian_test_plugin/test
create vendor/plugins/foradian_test_plugin/README
create vendor/plugins/foradian_test_plugin/MIT-LICENSE
create vendor/plugins/foradian_test_plugin/Rakefile
create vendor/plugins/foradian_test_plugin/init.rb
create vendor/plugins/foradian_test_plugin/install.rb
create vendor/plugins/foradian_test_plugin/uninstall.rb
create vendor/plugins/foradian_test_plugin/lib/fedena_test_plugin.rb
create vendor/plugins/foradian_test_plugin/tasks/fedena_test_plugin_tasks.rake
create vendor/plugins/foradian_test_plugin/test/fedena_test_plugin_test.rb
create vendor/plugins/foradian_test_plugin/test/test_helper.rb

Plugin Files

init.rb

require 'translator'
require File.join(File.dirname(__FILE__), "lib", "foradian_test_plugin")

FedenaPlugin.register = {
  :name=>"foradian_test_plugin",
  :description=>"Foradian Test Plugin"
  :more_menu=>{:title=>"Test Plugin",:controller=>"student",:action=>"index"}
}

Dir[File.join("#{File.dirname(__FILE__)}/config/locales/*.yml")].each do |locale|
  I18n.load_path.unshift(locale)
end

if RAILS_ENV == 'development'
  ActiveSupport::Dependencies.load_once_paths.\
    reject!{|x| x =~ /^#{Regexp.escape(File.dirname(__FILE__))}/}
end

Now this plugin creates a link to student search page in the more menu since we used the more_menu hook, which will be discussed later on.

Rakefile

require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

desc 'Default: run unit tests.'
task :default => :test

desc 'Test the foradian_test_plugin plugin.'
Rake::TestTask.new(:test) do |t|
  t.libs << 'lib'
  t.libs << 'test'
  t.pattern = 'test/**/*_test.rb'
  t.verbose = true
end

desc 'Generate documentation for the foradian_test_plugin plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
  rdoc.rdoc_dir = 'rdoc'
  rdoc.title = 'ForadianTestPlugin'
  rdoc.options << '--line-numbers' << '--inline-source'
  rdoc.rdoc_files.include('README')
  rdoc.rdoc_files.include('lib/**/*.rb')
end

fedena_test_plugin_tasks.rake

namespace :foradian_test_plugin do
  desc "Install Foradian Test Plugin Module"
  task :install do
    system "rsync --exclude=.svn -ruv vendor/plugins/foradian_test_plugin/public ."
  end
end

Readme

ForadianTestPlugin
==================

Introduction goes here.

Application files - Models, Views and Controllers

The application files should be placed in their respective folders in the 'app' folder under the folder of the plugin.

Migration Files

The migration files should be placed in the 'db/migrate' folder inside the plugin directory. i.e: {RAILS_ROOT}/vendor/plugins/{plugin_name}/db/migrate/ No columns in any tables of fedena should be changed. For creating association with the Fedena tables, join tables should be used.

Naming Controllers, Models and Databases

It is recommended to follow the naming conventions mentioned before while naming the controllers, models and database tables., i.e prefixing with suitable prefix so that plugin will not create a database or model with the same name as that used by fedena.

Using existing Controllers and Models

Associations for newer models to the existing ones should be defined in the init file. To make a code execute after rails initializes iniside a plugin, use the :after_initialize callback of rails initializer inside the plugin's init.rb,

#init.rb
config.after_initialize do
  Batch.send :has_many, :transports, :through=>:students
end

This method should be followed if we desire to add custom validations to any existing models in Fedena. Another way is to use Dispatcher.to_prepare method. Add a preparation callback. Preparation callbacks are run before every request in development mode, and before the first request in production mode. Use this inside the init.rb of the plugin. Custom methods can be added to existing models by defining the method inside a class of the destination model in the lib file. i.e if a custom method has to be used in the Student model,

#lib/foradian_test_plugin.rb
class Student
  def new_method
    #
  end
end

Note: The plugin's lib/* and init.rb are loaded before the rails load the models and controllers, so when you override a model/controller class by adding new method or by wrapping an existing method inside a plugin, make sure that piece of code is executed after rails initializes everything..

Adding custom validation to fedena

If there is a requirement of sole validation in fedena (eg :validate the format of student phone number ) . In such cases a validation plugin must be created and used likewise mentioned above under "Using existing Controllers and Models"

Available hooks

Hooks can be used in the file, init.rb inside the container FedenaPlugin.register = {} Following are the hooks available in Fedena.

name

Name of the plugin usage:

:name=>"foradian_test_plugin"

description

Description for the plugin usage:

:description=>"Foradian Test Plugin"

auth_file

File to look for the authorization rules usage:

:auth_file=>"config/transport_auth.rb"

more_menu

Adds a link to the drop-down menu 'more' usage:

:more_menu=>{:title=>"link_title",:controller=>"controller_name",:action=>"destination_action"}

sub_menus

Adds sub-menus to more_menu. usage:

:sub_menus=>[{:title=>"link_title", :controller=>"controller_name", :action=>"action_1"},
  {:title=>"link_title", :controller=>"controller_name", :action=>"action_2"}]

dashboard_menu

Add a link icon to the Fedena dashboard. usage:

:dashboard_menu=>{:title=>"link_label",:controller=>"controller_name",:action=>"action_name",
  :options=>{:class=>"option_buttons",:id => "id_of_button_in_css", :title => "description"}}

student_profile_more_menu

Adds a link to more menu in the student profile page. usage:

:student_profile_more_menu=>{:title=>"link_title",:destination=>{:controller=>"controller_name",
  :action=>"action_name"}}

employee_profile_more_menu

Adds a link to more menu in the employee profile page. usage:

:employee_profile_more_menu=>{:title=>"link_title",:destination=>{:controller =>"controller_name",
  :action=>"action_name"}}

finance

To list the finance transaction with the specified category name and prevent it from belonging to other transactions. usage:

:finance=>{:category_name=>"name_to_be_shown",:destination=>{:controller=>"controller_name" ,
  :action => "action_name"}}

css_overrides

To add some style modifications and add images such as for the dashboard buttons to the already existing pages. the modification should be made in a css file placed in the folder public/ stylesheets/plugin_css/ in the plugin folder and the filename should be the name of the plugin. for example, public/stylesheets/plugin_css/foradian_test_plugin.css usage:

:css_overrides=>[{:controller=>"user",:action=>"dashboard"}]

autosuggest_menuitems

This hook adds the provided search keyword to the autosuggest_menu to link with the specified controller and action. usage:

:autosuggest_menuitems=>[{:menu_type => 'link' ,:label => "search_keyword",
  :value =>{:controller => :controller_name,:action => :action_name}}]

instant_fees_index_link

Places a link at the fees index for the specified action. usage:

:instant_fees_index_link=>{:title=>"title",:destination=>{:controller=>"controller_name",
  :action=>"action_name"}, :description=>"link_description"}

generic_hook

Creates a link to a specified destination in the specified source controller and action. Destination action name and controller name are mandatory in this hook. The link would be placed in the dropdown list corresponding to the menu_id specified usage:

:generic_hook=>{:destination=>{:controller=>"student",:action=>"index"},
  :source=>{:controller=>"configuration",:action=>"index"},:menu_id=>"finance_menu"}

currently available menu ids: finance_menu

Dependency hooks

Dependency hooks are present for students and employees and are used to prevent them from removal if they have any dependencies such as dues etc. The page to be redirected to is given in the dependency hook in such cases. usage:

#lib/foradian_demo_plugin.rb
def self.student_dependency_hook
  "shared/student_dependency"
end

def self.employee_dependency_hook
  "shared/employee_dependency"
end

def self.dependency_check(record,type)
  if record.class.to_s == "ModelName"
    #what is left dependant
  end
end

#student_dependency and employee_dependency files in plugin_dir/views/shared/

Authorizations

Permissions to each and every action inside a controller should be specified for applicable roles in the file included in the hook ':auth_file'. Other hooks are dependant on the authorization rules in their working. Links will be shown only if the the logged in use has the privileges to that particular action.

Translations

Translation keywords should be used at every places where multiple language support is required. The keyword should be enclosed in t(" "). If it has to be displayed in views, it should be enclosed in ruby tag as en, . All the translations keywords and its translated words should be defined inside a yml file saved inside 'config/locales' directory inside the plugin folder and the following code has to be added to the init.rb file.

#init.rb
Dir[File.join("#{File.dirname(__FILE__)}/config/locales/*.yml")].each do |locale|
  I18n.load_path.unshift(locale)
end

for example:

#in view or erb files
<%= t("foradian_test_plugin_link") %>

#in controllers,models or other ruby files
t("foradian_test_plugin_link")

#railsroot/vendor/plufins/foradian_test_plugin/config/locales/en_foradian_test_plugin.yml
en:
  foradian_test_plugin_link: "Foradian test plugin"

Installing the plugin

To install the plugin run the following command in the terminal or console:

RAILS_ENV=production rake fedena:plugins:install_all

The installation task will run all the newer migrations and seeds to be added, if any present.

Download the Sample plugin