-
-
Notifications
You must be signed in to change notification settings - Fork 418
How to create a plugin
Plugins allow you to share and reuse common features. In this guide we're going to create a plugin called 'events'.
Plugins are a work in progress, suggestions for changes are welcome.
From an existing Spina app, run the rails generator for a 'full' rails engine:
rails plugin new vendor/plugins/events --full
This will create an engine inside your 'vendor/plugins' directory. Update the newly created gemspec with your contact information and add Spina as a dependency:
# /vendor/plugins/events/events.gemspec
Gem::Specification.new do |s|
s.name = "events"
s.version = Events::VERSION
s.authors = ["Your name"]
s.email = ["yourname@domain.com"]
s.homepage = "http://www.spinacms.com/"
s.summary = "Summary of Events."
s.description = "Description of Events."
s.license = "MIT"
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
s.test_files = Dir["test/**/*"]
s.add_dependency "rails", "~> 4.2.6"
s.add_dependency "spina", "~> 1.0.0"
s.add_development_dependency "sqlite3"
endSpina needs to know about our plugin. Add this initializer code to the engine:
# /vendor/plugins/events/lib/events/engine.rb
module Events
class Engine < ::Rails::Engine
initializer 'spina.plugin.register.events' do
::Spina::Plugin.register do |plugin|
plugin.name = 'Events'
plugin.namespace = 'events'
end
end
end
endFirst generate the model events inside the engine. Go to the plugin directory and run the generator:
cd vendor/plugins/events
rails g model spina/event title:string description:text date:datetime We want to be able to manage our new resource inside the Spina admin. Add the following routes:
# /vendor/plugins/events/config/routes.rb
Spina::Engine.routes.draw do
namespace :admin, path: Spina.config.backend_path do
resources :events, except: [:show]
end
endNotice that you have to change Events::Engine.routes.draw to Spina::Engine.routes.draw. This will add the routes to the existing Spina engine instead of the rails app.
Create the events controller:
# /app/controllers/spina/admin/events_controller.rb
module Spina
module Admin
class EventsController < AdminController
before_action :set_breadcrumb
before_action :set_event, only: [:edit, :update, :destroy]
layout 'spina/admin/website'
def index
@events = Event.all
end
def new
@event = Event.new
end
def edit
end
def create
@event = Event.new(event_params)
if @event.save
redirect_to admin_events_path, notice: 'Event was successfully created.'
else
render :new
end
end
def update
if @event.update(event_params)
redirect_to admin_events_path, notice: 'Event was successfully updated.'
else
render :edit
end
end
def destroy
@event.destroy
respond_to do |format|
redirect_to admin_events_path, notice: 'Event was successfully destroyed.'
end
end
private
def event_params
params.require(:event).permit(:title, :description, :date)
end
def set_breadcrumb
add_breadcrumb 'Events', admin_events_path
end
def set_event
@event = Event.find(params[:id])
add_breadcrumb @event.title
end
end
end
endAdd the following views:
-# /vendor/plugins/events/app/views/spina/admin/events/index.html.haml
.filters
= link_to 'New event', spina.new_admin_event_path, class: 'button button-primary', data: {icon: 't'}
.table-container
%table.table
%thead
%tr
%th Title
%th Date
%th
%tbody
- if @events.any?
- @events.each do |event|
%tr
%td
= event.title
%td
= l(event.date)
%td.nowrap.align-right
= link_to spina.edit_admin_event_path(event), class: 'button button-link' do
= icon('pencil-outline')
- else
%tr
%td.align-center{colspan: 3}
%em There are no events-# /vendor/plugins/events/app/views/spina/admin/events/_form.html.haml
= form_for [:admin, @event], html: {autocomplete: "off"} do |f|
- content_for :notification_alert do
= error_explanation!(@event)
#page_content.tab-content.active
.table-container
%table.table.table-form
%tr
%td
Title
%td
= f.text_field :title
%tr
%td
Description
%td
= f.text_area :description
%tr
%td
Date
%td
= f.text_field :date, value: (@event.date.strftime("%d-%m-%Y") unless @event.new_record?), class: 'datepicker'
%button.button.button-primary{type: 'submit', data: {icon: 'o'}}
Save
= link_to 'Cancel', admin_events_path, class: 'button button-link'
- unless @event.new_record?
.pull-right= link_to 'Delete', admin_event_path(@event), method: :delete, confirm: 'Are you sure?', class: 'button button-link button-danger'-# /vendor/plugins/events/app/views/spina/admin/events/new.html.haml
= render 'form'-# /vendor/plugins/events/app/views/spina/admin/events/edit.html.haml
= render 'form'Next we want to add a link to these actions inside the 'Your website' menu. For this reason Spina provides hooks to add your own navigation to existing menus. Create the following view:
-# vendor/plugins/events/app/views/spina/admin/hooks/events/_website_secondary_navigation.html.haml
%li{ class: ('active' if current_admin_path.start_with?('/events')) }
= link_to spina.admin_events_path do
= plugin.name
%small Here's where you can manage eventsThe location of this view is important. Spina will render views that are located in this 'hooks' directory (spina/admin/hooks/[plugin-name]). The view must have any of the following names:
_website_secondary_navigation.html_settings_secondary_navigation.html
If a plugin is active and has the correct name, then spina will automatically render the view.
The result will look like this:

Add the gem to the Gemfile to your main rails app:
gem 'events', path: 'vendor/plugins'
Add the plugin to your current theme, for example the default theme:
# /config/initializers/themes/default.rb
::Spina::Theme.register do |theme|
...
theme.plugins = ['events']
endNow you will be able to install the gem with bundle install, copy and install the migrations and restart your server.
bundle install
rake railties:install:migrations
rake db:migrate
touch tmp/restart.txt