# 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 (opens new window)
# 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