Creating custom Modules
Basicly there are two ways to set up a module:
- Use Alchemy as your Rails admin backend
- Create a new Engine
Generator
Alchemy provides a rails generator for custom modules, that can be invoked like this
bin/rails generate alchemy:module your_module_name
Using Alchemy as your Rails admin backend
Hence every module is a subsection of a Rails application or a gem you can roll out your own admin backend if you like.
By using Alchemy's backend interface you get a whole bunch of things:
- Authentication and Authorization
- A highly and fine grained customizable resource manager (CRUD interface)
- A nicely styled user interface
And it's easy as this:
module Admin
class YourResourcesController < Alchemy::Admin::ResourcesController
end
end
You can overwrite the default controller actions and views as you like. An instance-variable named after the resource (i.e. @your_resource
for YourResource
) is defined for use in your views.
After you setting up your routes you have to take care for control access:
Authorization
Rights and roles are set in a CanCan Ability model. Create the file if it doesn't exist already. It has to be registered manually, by invoking Alchemy.register_ability MyModuleAbility
in the module initializer.
# app/models/my_module_ability.rb
class MyModuleAbility
include CanCan::Ability
def initialize(user)
if !user.blank? && user.is_admin?
can :manage, YourResource
can :manage, :admin_your_resources
end
end
end
More information about authorization can be found in the docs of the cancancan
gem
Routing
In an engine
# config/routes.rb
YourApp::Application.routes.draw do
...
mount YourAlchemyModule::Engine => '/'
mount Alchemy::Engine => '/'
end
In your app
# config/routes.rb
YourApp::Application.routes.draw do
resources :your_resource
namespace :admin do
resources :your_resource
end
mount Alchemy::Engine => '/'
end
TIP
Due to Alchemy's strong routes it is strongly recommended to mount your engine before Alchemy.
Registering the module
Last but not least the module needs to be registered to AlchemyCMS.
When using your host app
# my_host_app/config/initializers/alchemy_modules.rb
Alchemy::Modules.register_module({
name: 'name_of_your_module',
order: 1, # The position in main navigation, if you have more than 1 module.
navigation: {
name: 'modules.products', # The name in the main navigation (translated via I18n).
controller: '/admin/products', # The controller that will be used.
action: 'index', # The controller action that will be used.
icon: 'module_icon', # Class of icon that will be rendered as navigation icon.
sub_navigation: [
{
name: 'modules.products', # The name for the subnavigation tab (translated via I18n).
controller: '/admin/products', # Controller that will be used.
action: 'index' # Controller action that will be used.
},
{
name: 'modules.variants', # The name for the subnavigation tab (translated via I18n).
controller: '/admin/variants', # Controller that will be used.
action: 'index' # Controller action that will be used.
}
]
}
})
# Register the module ability
Alchemy.register_ability MyModuleAbility
NOTE: As an alternative to the module icon you can pass: image: '/alchemy/icon_of_your_module.png'
Using a Rails engine
# my_engine/config/initializers/alchemy.rb
Alchemy::Modules.register_module({
name: 'name_of_your_module',
engine_name: 'name_of_your_engine' # The engine_name set in your Rails::Engine class.
order: 1, # The position in main navigation, if you have more than 1 module.
navigation: {
name: 'modules.products', # The name in the main navigation (translated via I18n).
controller: '/admin/products', # The controller that will be used.
action: 'index', # The controller action that will be used.
icon: 'module_icon', # Class of icon that will be rendered as navigation icon.
sub_navigation: [
{
name: 'modules.products', # The name for the subnavigation tab (translated via I18n).
controller: '/admin/products', # Controller that will be used.
action: 'index' # Controller action that will be used.
},
{
name: 'modules.variants', # The name for the subnavigation tab (translated via I18n).
controller: '/admin/variants', # Controller that will be used.
action: 'index' # Controller action that will be used.
}
]
}
})
# Register the module ability
Alchemy.register_ability MyModuleAbility
Translate your module names
All module names are passed through I18n within a alchemy
namespace. The name will be used as translation key. You should namespace your module name (with i.e. modules
), to prevent conflicts.
Example
Given a module name modules.products
your translation has to be:
# config/locales/de.yml
de:
alchemy:
modules:
products: Produkte