Instiki is a great wiki system, which I am using to drive the content of http://www.netxforge.com. Instiki however is behind in respect of the Rails version it was created with. This is a problem for me, as I want to integrate instiki, into a broader Ruby On Rails application.
This blog describes the steps I took to do it. The conversion is unfortunately not available as a download or on a repo somewhere, but I hope that the list of issues (And how I solved them) can help others to repeat it and make the upgrade available.
The creator of Instiki, alias Distler has endorsed this initiative in the instiki forum.
So here are the steps:
Warning: some of the stuff is perhaps a bit specific to my setup so be carefull. Also I haven't done everything yet, and some things don't work correctly. One example is the use of JavaScript. In rails 3, JQuery is favoured over Prototype.js etc... , the use of assets and separation of Javascript from erb templates is good practise. Some of this is still to be done.
----- (I Recommend to start the server after each step, to get a feel of the progress)
Step 1. Use a rails 3.2 generated app to compare the current instiki and the rails 3.2 structure. We refer to this as the Template Rails App (TRA)
Step 1.1 Update the Gemfile (It now looks like this, see explanation in separate steps)
source "http://rubygems.org" gem "rails", "=3.2.12" # Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' # See https://github.com/sstephenson/execjs#readme for more supported runtimes # gem 'therubyracer', :platforms => :ruby gem 'uglifier', '>= 1.0.3' end gem 'jquery-rails' gem "sqlite3", :require => "sqlite3" gem "itextomml", ">=1.4.10" gem "rack", ">=1.4.5" gem "mongrel", ">=1.2.0.pre2" gem "rubyzip" gem "RedCloth", ">=4.0.0" gem "erubis" gem "nokogiri" gem "rake" gem "rdoc" gem "json" gem "file_signature", :git => 'http://github.com/distler/file_signature.git' gem "maruku", :git => 'http://github.com/distler/maruku.git', :branch => 'nokogiri' # gem "mysql2"Step 2. Replace the /script's content with the TRA's /scripts content, delete the old files from /script
Step 3. Migration of the /config folder
Step 3.1 Create application.rb (Rails 3. has an application.rb file) and configure it in the steps below.
Load the /lib folder as this is turned off, edit/add these params.
config.autoload_paths << "#{Rails.root}/lib" config.autoload_paths << "#{Rails.root}/lib/chunks"Do some java script setup, for the new rails 3 assets concept. Instiki should actually migrate away from scriptaculous.js and use JQuery
config.action_view.javascript_expansions[:legacy] = %w(prototype.js scriptaculous.js)
Step 3.3 copy in the environments/ and initializers/ from TRA
The TRA application name will be different then what Instiki should be. The following file should be edited and the first line should be renamed from
"TemplateApp::Application.configure do" to "InstikiApp::Application.configure do"
config/environments/development.rb
config/environments/test.rb
config/environments/production.rb
Step 3.4 move the original environment.rb out of the way (renamed it to environment.rb.backup), and copy the environment.rb from the template rails app
Some migrations from the contents of this file.
Rename the last line to InstikiApp::Application.initialize!
require_dependency 'instiki_errors' => Moved this to a custom initializer named config/initializers/instiki_init.rb It looks like this:
require 'instiki_errors' require 'wiki_content'
require 'instiki_errors' # migrated from instiki environment.rb
require 'wiki_content' # Needed to load properly [TODO]
rexml_versions => Not sure what to do with this. It scans various directories to get an REXML version.
# Miscellaneous monkey patches (here be dragons ...)
require 'caching_stuff'
require 'logging_stuff' require 'rack_stuff' Note: Not using require_dependency, as this is undocumented (Rails internal) and for development only. Not really a requirement here I believe.
Step 3.4 Copy in boot.rb from TRA, remove preinitializer.rb which is a pre Rails 3 hack to get bundler working.
See: http://gembundler.com/v1.3/rails23.html
Step 3.5 root.rb [Carefull] This route.rb is slightly specific to my application, but it includes the wiki routes, so you can extract the relevant ones:
[TODO] some routes don't work in the rails 3. instill, need to be fixed.
def connect_to_web(generic_path, generic_routing_options, *options) if defined? DEFAULT_WEB explicit_path = generic_path.gsub(/:web\/?/, '') # Strip the /:web explicit_routing_options = generic_routing_options.merge(:web => DEFAULT_WEB) match explicit_path, explicit_routing_options end match generic_path, generic_routing_options # map.connect(generic_path, generic_routing_options) end # :id's can be arbitrary junk id_regexp = /.+/ InstikiApp::Application.routes.draw do # SEE: http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/ root :to => 'public#page', :id => 'HomePage' # Wiki Admin: match 'create_system', :to => 'admin#create_system' match 'create_web', :to => 'admin#create_web' match 'delete_web', :to => 'admin#delete_web' match 'delete_files', :to => 'admin#delete_files' match 'web_list', :to => 'wiki#web_list' # Application match ':controller/:action(/:id)' # Wiki webs routing connect_to_web ':web/edit_web', :to => 'admin#edit_web' #Edit an arbitrary web. connect_to_web ':web/remove_orphaned_pages', :to => 'admin#remove_orphaned_pages' #Remove pages which are not referenced by any other page connect_to_web ':web/remove_orphaned_pages_in_category', :to => 'admin#remove_orphaned_pages_in_category' connect_to_web ':web/file/delete/:id', :to => 'file#delete', :constraints => {:id => /[-._\w]+/}, :id => nil connect_to_web ':web/files/pngs/:id', :to => 'file#blahtex_png', :constraints => {:id => /[-._\w]+/}, :id => nil connect_to_web ':web/files/:id', :to => 'file#file', :constraints => {:id => /[-._\w]+/}, :id => nil connect_to_web ':web/file_list/:sort_order', :to => 'wiki#file_list', :sort_order => nil connect_to_web ':web/import/:id', :to => 'file#import' connect_to_web ':web/login', :to => 'wiki#login' connect_to_web ':web/web_list', :to => 'wiki#web_list' connect_to_web ':web/show/diff/:id', :to => 'wiki#show', :mode => 'diff', :requirements => {:id => id_regexp} connect_to_web ':web/revision/diff/:id/:rev', :to => 'wiki#revision', :mode => 'diff', :constraints => { :rev => /\d+/, :id => id_regexp} connect_to_web ':web/revision/:id/:rev', :to => 'wiki#revision', :constraints => { :rev => /\d+/, :id => id_regexp} connect_to_web ':web/source/:id/:rev', :to => 'wiki#source', :constraints => { :rev => /\d+/, :id => id_regexp} connect_to_web ':web/list/:category', :to => 'wiki#list', :constraints => { :category => /.*/}, :category => nil connect_to_web ':web/recently_revised/:category', :to => 'wiki#recently_revised', :requirements => { :category => /.*/}, :category => nil connect_to_web ':web/:action/:id', :to => 'wiki', :constraints => {:id => id_regexp} connect_to_web ':web/:action', :to => 'wiki' connect_to_web ':web', :to => 'wiki#index'
Step 4 problem with plugin: protect_forms_from_spam, comment it out. Find an alternative
Step 5. Deal with assets (Stylesheets, Javascript, Images)
Read this: http://guides.rubyonrails.org/asset_pipeline.html
Assets should be pre-compiled with:
bundle exec rake assets:precompile
these will end up in the /public/assets/ folder
Step 5.1 Update the Gemfile to include:
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
Step 5.2 Create asset folders
/app/assets/stylsheet
- copy in application.css from TRA
- [OPTIONAL] rename .css to .css.erb to use assets in CSS for example: <%= asset_path 'someimage.png' %>
/app/assets/javascript
- application.js is auto created, but we already have an application.js file with a bit of scripts in it. so copy the following lines
from TRA and add them to the instiki application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
/app/assets/images
- use image_tag helper methods.
Step 5.3
Copy in the assets from /public in the respective locations under /aspp/assets from the 2.x instiki
Step 6 Replace @controller with controller wherever this occurs in the controllers.
Step 7. Fix issues with rendering and default.layout/
[DEBUG]: Render an action without the layout for troubleshooting: render :layout => false
fix the layout content insertion point, was @content_for_layout versus modern yield. so => <%= yield %>
Use: <%= debug params %>
Step 8. problem with sublayout: (Wiki source)
Showing /Users/Christophe/Documents/Spaces/netxforge_aptana/com.netxforge.store/app/views/layouts/application.html.erb where line #46 raised:
undefined method `sub_layout' for #<WikiController:0x007ffb07b5bf58>
Step 9. link_to_remote issues: , now workaround, not using the :update tag. [TODO]
Currently URL's like this are generated, which embeds a js into the URL with onclick statement).
<a onclick="new Ajax.Updater('intropage', '/public/page/features?menu=true&partial=true',
{asynchronous:true, evalScripts:true}); return false;" href="#"></a>
:update is not supported anymore in Rails 3. (AJAX call back to update a DOM id), see the following articles:
http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-technique/
New approach is based on separation of the HTML and JS, so the JS should do the update.
Step 10. Issues with form_tag
in template edit.html.erb, the form tag starts with '<%' erb shabang, but should be '<%='
replacing this fixed the problem.
See 3.0 Release notes, section 7.4.2.
Note: The included javascript should be moved to the application.js or another .js under /app/assets/javascript
Step 11. ActiveModel::MassAssignmentSecurity erros on various model objects[SOLVED]
because of this:
https://gist.github.com/peternixey/1978249
in various model objects, to fix these errors.
Page => attr_accessible :locked_at, :locked_by, :name
Revision=> attr_accessible :revised_at, :page, :content, :author
.....
Step 12. Undefined method error in WikiContent[SOLVED]
It turned out, that
include ChunkManager (in wiki_content.rb) didbn't load properly, as
ChunkManager has dependencies on various other classes in /chunks.
Made sure these are loaded in application.rb (See Step 3.1)
however this causes another issue:
Step 12.1 Error, when include /lib/chunks
Expected .../lib/chunks/wiki.rb to define Wiki
Actually the whole app now fails with different errors:
This could be a conflict in naming of classes, as /chunks defines a wiki.rb
See this post:
http://stackoverflow.com/questions/10948779/expected-to-define-when-calling-class-inside-a-module
fixed by:
- renamed wiki to wiki_c and references to it.
- removed call to html_safe in WikiContent.render! as this points to a method which
will produce a ActiveSupport::SafeBuffer instance from the WikiContent, so not adhering to the instance type,
this gived method_errors
Step 13. URL generator in wiki gives wrong urls for: [TODO]
all Pages => /:web/list/HomePage (So the :page is appended and shou'd not).
edit Web => /:web/edit_web/HomePage (:page appended, should not).
Step 14. Dealing with XML templates.
renamed atom.rxml to atom.builder simply solved the problem.
Step 15. Grab a coffee, and reflect on your great achievements sofar :-)
Step 16. Warning: You don't need to install rails_xss as a plugin for Rails 3 and after. [TODO]
http://simianarmy.com/post/11117853564/upgrading-to-rails-3-rails-xss
- What to do with this? It's not clear to me what the new situation is.
Step 17. [2013-03-13 12:26:00] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
Caused by webrick server, don't worry about it.
In the spirit of open source, have you posted your fork of Instiki anywhere?
ReplyDelete