Part 2: Using Engines to extend Refinery CMS
Alright, for those that don't know, engines (formally known as plugins) are a way to add functionality to your site. Engines create a tab in the backend that allow users that aren't tech savvy to enter information in a very user friendly way. Let's start off with an example.
The code below is the basic layout for building an engine and we will go more in depth afterward.
rails generate refinery_engine engine_name attribute:type attribute:name...
bundle install
rails generate refinerycms_engine_names
rake db:migrate
Some things to remember:
- rails generate refinery_engine engine_name. Must be singular.
- Everything must be lowercase.
- rails generate refinerycms_engine_names. Must be plural.
Creating your Engine
Say you want to add the ability for people to add staff members into the back end.
rails generate refinery_engine staff_member name:string title:string thumbnail:image image:image bio:text
bundle install
rails generate refinerycms_staff_members
rake db:migrate
Keep in mind that your engine won't display in the backend locally unless you restart your local server.
Deleting your Engine
Deleting your engine after:
rails generate refinery_engine engine_name attribute:type
Inside your Gemfile, delete the last last line created that will looked something like gem 'refinerycms-staff-members', '1.0', :path => 'vendor/engines', :require => 'staff-members'. Delete the folder staff_members, under vendors->engines.
After this, the engine should be deleted and free free rerun the code.
Deleting your engine after:
rails generate refinerycms_engine_names
Inside your Gemfile, delete the last last line created that will looked something like gem 'refinerycms-staff-members', '1.0', :path => 'vendor/engines', :require => 'staff-members'. Delete the folder staff_members, under vendors->engines. Delete the newly created migration in db-> migrate-> 20110120160306_create_staff_members.rb
Deleting your engine after:
rake db:migrate
Inside your Gemfile, delete the last last line created that will looked something like gem 'refinerycms-staff-members', '1.0', :path => 'vendor/engines', :require => 'staff-members'. Delete the folder staff_members, under vendors->engines. Delete the newly created migration in db-> migrate-> 20110120160306_create_staff_members.rb Then run:
rake db:rollback
I have had some issues trying to recreate an engine with the same do to the this line in the migration not correctly functioning.
UserPlugin.destroy_all({:name => "Staff Members"})
The issue seems to be that the name of the plugin is actually "staff_members". The plugin doesn't get deleted out of the database and therefore the throws a non unique :name error. If you are getting this error, try running this code.
heroku console (or rails console to do it locally)
a = UserPlugin.first(:conditions => {:name => "staff_members"});
a.destroy
exit
You should now be able to run:
rake db:migrate
Adding Additional Fields to your Engine
Say you want to create an Active field where you can toggle off active members. First we need to generate a new migration.
rails generate migration add_active_field
The name of the migration doesn't matter as long as you don't already have a migration with the same name. Try to make your migrations as descriptive as possible though.
Your new migration should currently look like:
class AddActiveField< ActiveRecord::Migration
def self.up
end
def self.down
end
end
We are now going to add the active field to the database. So change your migration to look like (more detailed options below):
class AddActiveField< ActiveRecord::Migration
def self.up
add_column :staff_members, :active, :boolean
end
def self.down
remove_column :staff_members, :active
end
end
The simply adds a field called active with the field type boolean to the staff_members table. By default, all existing staff_members will have the active field value equal to nil and default to false when creating a new staff member. If we wish to have a current staff members to have the value active and have the default when creating a new member to true, put this code in your migration instead.
class AddActiveField< ActiveRecord::Migration
def self.up
add_column :staff_members, :active, :boolean, :default => true
StaffMember.all.each do |member|
member.active = true
member.save
end
end
def self.down
remove_column :staff_members, :active
end
end
rake db:migrate
You'll have to restart your server after making database changes if working locally. Now that we have the database set up correctly, the active field doesn't magically get added to our engine form. So to have the the code to the form located under vendor-> engines-> staff_members-> app-> views-> admin-> staff_members-> _form.html.erb. Once there, just simply add this code where you would like the checkbox to display.
<%= f.label :active %>
<%= f.check_box :active %>
You should now see a checkbox on your forms.
Pushing Your Code Live
In order to get your engine live on your Heroku server:
git add *
git commit -a -m "Add staff members engine"
git push
git push heroku master
heroku rake db:migrate
Other useful things to Know
Changing the Titles of your Engines
Refinery engines by default are in plural, so if you create a management engine, it will call it Managements and the tab in the backend will be labeled Managements. If you wish to change the label in the backend go to vendor-> engines-> managements-> config-> locales-> en.yml. There you should see:
plugins:
managements:
title: Managements
Simply change the title and save.
Making fields required
Navigate into the model folder of your engine vendor-> engines-> staff_members-> app-> models-> staff_member.rb. Inside this file by default, it requires the first text field and makes sure this field is unique. We might not always want to the first field to be unique or required and we may want additional fields require or unique. Change it form:
validates_presence_of :name
validates_uniqueness_of :name
To:
validates_presence_of :name
validates_presence_of :image
validates_presence_of :title
validates_presence_of :bio
This will require you to have these 4 fields filled out in order to submit, but none of them have to be unique.
