Thu Mar 29 02:50:00 UTC 2007

Using Textile Editor Helper and acts_as_textiled

Posted in Ruby on Rails at 02:50 AM by mohits

One of the ways to allow lean markup for text is to use Textile for the text fields. Using acts_as_textiled can make this process even easier. The only thing that was missing was to have a way to allow users to enter Textile-formatted text with greater ease… until now, that is!

Enter the Textile Editor Helper to ease this step. This article just takes you step-by-step to show you how to get a Textile-enabled field working in your Rails app.

Install RedCloth if needed

To use Textile, you must install the RedCloth gem first.


1
2
3
4
5
6
rails_apps>gem install RedCloth
Attempting local installation of 'RedCloth'
Local gem file not found: RedCloth*.gem
Attempting remote installation of 'RedCloth'
Updating Gem source index for: http://gems.rubyforge.org
Successfully installed RedCloth-3.0.4

Create a new Rails app

I want to assume nothing, so I’ll just start from scratch here. Create a new Rails app by using the usual way.


1
2
3
4
rails_apps>rails ted_sample
      create
      create  app/controllers
      ... 

Create the database for it

Using whatever method you prefer, create a database (command line, phpMyAdmin, etc.) for the application. In my case, I added a database called ‘sample’ to MySQL running on my localhost.

Adjust the connection properties

Go to

rails_app\ted_sample\config
and edit
database.yml
to point to the actual database. I’m using development mode only (this application has a life of 10 minutes) and the database properties need to be set as above.


1
2
3
4
5
6
development:
  adapter: mysql
  database: sample
  username: <put db user name>
  password: <put password>
  host: localhost

Install the plugin – acts_as_textiled

You can get the details to install the

acts_as_textiled
plugin from the link above. But, it’s quite simple to do.


1
2
3
4
5
6
rails_apps\ted_sample>ruby script/plugin install svn://errtheblog.com/svn/plugins/acts_as_textiled
A    E:\InstantRails\rails_apps\ted_sample\vendor\plugins\acts_as_textiled
A    E:\InstantRails\rails_apps\ted_sample\vendor\plugins\acts_as_textiled\test
A    E:\InstantRails\rails_apps\ted_sample\vendor\plugins\acts_as_textiled\test\memory_test_fix.rb
A    E:\InstantRails\rails_apps\ted_sample\vendor\plugins\acts_as_textiled\test\setup_test.rb
...

That prepares you to do the first bit. But while we are at it, let’s also put in the Textile Editor Plugin, shall we?

Install the plugin – Textile Editor Helper

This one is equally simple. From the root directory of your Rails app, just run the following:


1
2
3
4
5
6
7
rails_apps\ted_sample>script/plugin install http://svn.webtest.wvu.edu/repos/rails/plugins/textile_editor_helper/
+ ./textile_editor_helper/MIT-LICENSE
+ ./textile_editor_helper/README
+ ./textile_editor_helper/Rakefile
+ ./textile_editor_helper/assets/images/textile-editor/background.png
+ ./textile_editor_helper/assets/images/textile-editor/blockquote.png
...

Now, run the install script for it.


1
2
3
4
5
6
7
rails_apps\ted_sample>rake textile_editor_helper:install
(in rails_apps/ted_sample)
 * Copying /assets/images/textile-editor/background.png       to /public/images/textile-editor/backg
round.png
 * Copying /assets/images/textile-editor/blockquote.png       to /public/images/textile-editor/block
quote.png
...

Create the first model

OK, from the root directory of your Rails application and generate the first model


1
2
3
4
5
6
7
8
9
rails_apps\ted_sample>ruby script\generate model item
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/item.rb
      create  test/unit/item_test.rb
      create  test/fixtures/items.yml
      create  db/migrate
      create  db/migrate/001_create_items.rb

Edit the migration file

The next step is to add in the details about the model into the migration file. Open up

db/migrate/001_create_items.rb
and modify it so it looks something like this.


1
2
3
4
5
6
7
8
9
10
11
12
class CreateItems < ActiveRecord::Migration
  def self.up
    create_table :items do |t|
      t.column :name, :string, :null => false
      t.column :descr, :text
    end
  end

  def self.down
    drop_table :items
  end
end

And apply the migration as always.


1
2
3
4
5
6
rails_apps\ted_sample>rake db:migrate
(in rails_apps/ted_sample)
== CreateItems: migrating =====================================================
-- create_table(:items)
   -> 0.0900s
== CreateItems: migrated (0.0900s) ============================================

OK, time to go to the application now and actually use the plugins.

Identify the field for Textiled data

Open your model file

apps\models\item.rb
in an editor and change it to something like the one shown below, marking
descr
as the textiled field.


1
2
3
class Item < ActiveRecord::Base
    acts_as_textiled :descr
end

Create the controller and view for the model

OK, I’m going to cheat here and just use a scaffold to get this done faster.


1
2
3
4
5
rails_apps\ted_sample>ruby script\generate scaffold item
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/items
      ...

Include prototype.js

The Textile Editor Helper relies on

prototype.js
for some features. So, you need to ensure that it is included in the final page that is rendered. One of the easiest ways (for this sample) is to include it in the layout for the
item
class. Edit
ted_sample\app\views\layouts\items.rhtml
to include a call to
javascript_include_tag
in the header part of the file.


1
2
3
4
5
6
7
8
...
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Items: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
  <%= javascript_include_tag 'prototype' %>
</head>
...

Modify the form to use the Textile Editor Helper

(This information is direct from the Textile Editor Helper website)

Navigate to the

app\views\items\_form.rhtml
so that we can add in the code for the helper.

Replace the text area tag with <%= textile_editor 'object', 'field' -%> This accepts the same options as the regular text area tag. Also, at the end of the form, put in the following code: <%= textile_editor_initialize -%>

Once this is done, the

app\views\items\_form.rhtml
file will look something like this.


1
2
3
4
5
6
7
8
9
10
11
<%= error_messages_for 'item' %>

<!--[form:item]-->
<p><label for="item_name">Name</label><br/>
<%= text_field 'item', 'name'  %></p>

<p><label for="item_descr">Descr</label><br/>
<%= textile_editor 'item', 'descr' -%>

<!--[eoform:item]-->
<%= textile_editor_initialize -%>

One small change

Since we are using the scaffold, it escapes all the data when it outputs it. What this means is that if you use it as it is, the textiled fields will display the actual HTML code rather than rendering it. So, we can change the show.rhtml and list.rhtml files to render the actual text. I’m changing just the

app/views/items/show.rhtml
file to the code below – you can change the other one if you want.


1
2
3
4
5
6
<p><b>Name:</b> <%=h @item.name %></p>
<p><b>Description:</b></p> 
<%= @item.descr %></p>

<%= link_to 'Edit', :action => 'edit', :id => @item %> |
<%= link_to 'Back', :action => 'list' %>

Start the Server


1
2
3
4
rails_apps\ted_sample>ruby script\server
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
...

Go to http://localhost:3000/items/ to see how it works.

Comments »

  1. Benny said,

    April 10th, 2007 at 08:31 PM

    one remark; since the

    textile_editor_initialize
    thingie outputs not only <script> tags, but also a <link> tag to include the css. Because of this, if you want your page to be valid HTML, it has to go in the head of the document. (see http://www.w3.org/TR/html4/struct/links.html#h-12.3).

    I don’t know why this and the original howto says that the initialize line has to go below the form; it seems to work just fine from within the head as well. I use following line to include it;

    <%= textile_editor_initialize unless !%w(create edit).include?(@controller.action_name) -%>

    Also, you should really make this comment textarea bigger, and perhaps add preview functionality..

  2. Mohit said,

    April 13th, 2007 at 12:17 AM

    Hi Benny,

    Thanks for pointing that out. I actually put it in this way cos I followed the instructions on the original site. But, thanks for your alternative. I’m sure it will help :)

    As regards the comment area, well, frankly I’m still struggling with Mephisto – I do need to figure it out.

    Preview functionality is there on the original site – didn’t want to replicate that.

    Cheers, Mohit.

  3. Benny said,

    April 13th, 2007 at 02:23 AM

    my pleasure,

    meanwhile, i’ve been trying to make a plugin myself to put WYMeditor on rails. might you not know WYM, it beats the crap out of most WYSIWIG editors qua preserving W3C specs compatibility. I just need a little help finishing up since a part of the js doesn’t seem to work.. Might you or anyone care, check my post on WYM’s wiki at http://dev.wymeditor.org/wiki/index.php/Docs/WymOnRails

  4. Mohit said,

    April 13th, 2007 at 11:55 AM

    Excellent! I look forward to that :)

    By the way, managed to temporarily fix the Comments Area size problem by switching the theme – I still need to get my head around Mephisto :P

    Cheers Mohit

  5. Zubin said,

    April 17th, 2007 at 04:15 PM

    Great helper, but does anyone know if/how it works with form_for?

    This does not work:

    <% form_for :item, @item, :url => {:action => “update”} do |f| %> <%= f.textile_editor ‘description’ %>

    <% end %>

    Error: undefined method `textile_editor’ for #<actionview::helpers::formbuilder:0x354b5e8>

  6. pingala said,

    April 19th, 2007 at 04:36 AM

    i’m trying to install actings_as_textile… but the svn is not working:

    tumma@tumma:~/MyDev/chit$ ./script/plugin install svn://errtheblog.com/svn/plugins/acts_as_textiled sh: svn: not found

    does anybody know what the problem is?

    thanks.

  7. Mohit said,

    April 23rd, 2007 at 12:20 AM

    Hi Pingala It seems that the command line could not find svn… is it installed?

    You may want to try asking on the Ruby on Rails Google Group – you’re likely to get a quicker/ better response there.

    Cheers, Mohit.

  8. jean-sebastien said,

    April 25th, 2007 at 09:14 AM

    I’ve followed the tutorial but bottom buttons (to save and preview) do not appear. any idea?

  9. Mohit said,

    April 25th, 2007 at 09:26 AM

    Hi Jean-Sebastian

    It’s normal to not see any ‘Save’ and ‘Preview’ buttons.

    There is nothing in the code to make that happen. This was just a basic tutorial to get you started in the correct direction (and also to make a note so that I know what to do next time I need to use it).

    You should see a ‘create’ button, though, at the bottom? Cheers Mohit.

  10. jean-sebastien said,

    April 26th, 2007 at 06:08 AM

    thank you Mohit. I’m confused, i thought those buttons were integrated in the form created by the plugin.

  11. xvridan said,

    June 5th, 2007 at 06:36 PM

    Why does it display such as : “laaa,is”. it isn’t laaadeleted text

    I had installed the RedCloth. And like your step above (Sorry, my English is pool.)

  12. Mohit said,

    June 6th, 2007 at 11:33 AM

    Hi xvridan,

    I’m sorry I don’t fully understand your problem. Are you having trouble in installing RedCloth or using Textile?

    Cheers Mohit.

  13. railsgrunt said,

    June 16th, 2007 at 02:07 AM

    i am trying to get this plugin to work with my existing app but for some reason or another, the toolbar is not rendering. i get no other error output to the logger. any ideas? i am linking prototype, ran teh instal command, and copied both the teh text area and initialize, etc…

  14. railsgrunt said,

    June 16th, 2007 at 02:59 AM

    i have a weird issue. i have a note that is inside a note div. the note also contains a edit button which replaces all the html inside that div with the form. however in this case, the toolbar does not render. however, when i place my form in a regular view outside of my div, the toolbar renders. any idea?

    thanks

  15. Ray said,

    June 30th, 2007 at 04:17 AM

    I am also looking for a way to get the editor to show up correctly thru an Ajax response from the server. I used a link_to_remote to retrieve the form with the TEH editor inside the form. I got the form in the browser, but it is displayed as a regular form, not the TEH editor.

    I haven’t looked into the Javascripts too much at all. But I am thinking that the Javascripts for TEH only gets called during an onload, not on subsequent Ajax responses from the server.

    I also tried widgEditor, and it is the same thing.

  16. Ray said,

    July 11th, 2007 at 03:47 AM

    I spent a little time looking at the code, and found that if you manually include the TEH javascript and stylesheet files, you can use Ajax to retrieve the TEH editor in a partial containing the call the textile_editor_initialize.

    (1) Include these in a layout:

    <%= stylesheet_link_tag ‘textile-editor’, :media => :screen %> <%= javascript_include_tag ‘textile-editor’ %>

    (2) Change edit.rhtml to the following:

    Editing item

    <%= link_to_remote “Show the Ajax editor”, :url => { :action => :get_ajax_editor } %>

    <%= link_to ‘Show’, :action => ‘show’, :id => @item %> | <%= link_to ‘Back’, :action => ‘list’ %>

    (3) Change _form.rhtml to the following:

    <% remote_form_for :item, :url => { :action => :update, :id => @item } do |f| -%>

    <%= error_messages_for ‘item’ %>

    <!-[form:item]->

    <label for='item_name'>Name</label>
    <%= f.text_field ‘name’ %>

    <label for='item_descr'>Descr</label>
    <= textile_editor ‘item’, ‘descr’ ->

    <!-[eoform:item]-> <= textile_editor_initialize -> <%= submit_tag ‘Edit’ %> <% end -%>

    (4) Add _ajax_result.rhtml

    Name: <%=h @item.name %>

    Description: <%= @item.descr %>

    (5) Change items_controller.rb to the following

    def get_ajax_editor
      @item = Item.find(:first)
    end
    render :update do |page|
      page.replace_html 'ajax_editor', :partial => 'form'
    end
    def update
      @item = Item.find(params[:id])
    end
    render :update do |page|
      if @item.update_attributes(params[:item])
        page.replace_html 'ajax_result', :partial => 'ajax_result', :object => @item
      else
        page.replace_html 'ajax_result', 'Item failed to be updated.'
      end
    end

    Try it out !

  17. Mohit said,

    July 13th, 2007 at 01:15 PM

    Hi Ray

    Thanks a lot! I think that will help quite a few people :)

    Cheers

    Mohit

  18. Ray said,

    July 13th, 2007 at 02:57 PM

    I didn’t realize the comment was using markup…

    I posted in my blog as well.

Sorry, comments are closed for this article.