views:

271

answers:

1

I am trying to develop a plugin for Ruby on Rails and came across problems rendering my html view. My directory structure looks like so:

File Structure

---/vendor
      |---/plugins
             |---/todo
                     |---/lib
                            |---/app
                                    |---/controllers
                                            |---todos_controller.rb
                                    |---/models
                                            |---todos.rb
                                    |---/views
                                            |---index.html.erb
                             |---todo_lib.rb
                     |---/rails
                             |---init.rb

In /rails/init.rb

require 'todo_lib'

In /lib/app/todo_lib.rb

%w{ models controllers views }.each do |dir|
  # Include the paths:
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/lib/app/models
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/lib/app/controllers
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/lib/app/views
  path = File.expand_path(File.join(File.dirname(__FILE__), 'app', dir))
  # We add the above path to be included when Rails boots up
  $LOAD_PATH << path
  ActiveSupport::Dependencies.load_paths << path
  ActiveSupport::Dependencies.load_once_paths.delete(path)
end

In todo/lib/app/controllers/todos_controller.rb

class TodosController < ActionController::Base
  def index
  end
end

In todo/lib/app/views/index.html.erb

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "[url]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd[/url]"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Todos:</title>
</head>
<body>
<p style="color: green" id="flash_notice"><%= flash[:notice] %></p>
<h1>Listing Todos</h1>
</body>
</html>

In /myRailsApp/config/routes.rb

ActionController::Routing::Routes.draw do |map|
  # The priority is based upon order of creation: first created -> highest priority.

  map.resources :todos
  ...

The error I get is the following:

Template is missing

Missing template todos/index.erb in view path app/views

Can anyone give me a hand up and tell me what am I doing wrong here that is causing my index.html.erb file to not render? Much appreciated!


EDIT:

I have already tried the following without success:

In /todo/lib/app/controllers/todos_controller.rb

def index
   respond_to do |format|
      format.html # index.html.erb
    end
end

EDIT:

hakunin solved this problem. Here's the solution.

He says that I'm building a Rails engine plugin (I had no idea I was doing this), and it requires a different directory structure, one that appears like so:

File Structure

---/vendor
      |---/plugins
             |---/todo
                     |---/lib
                     |---/app
                            |---/controllers
                                    |---todos_controller.rb
                            |---/models
                                    |---todos.rb
                            |---/views
                                    |---/todos
                                            |---index.html.erb
                            |---todo_lib.rb
                     |---/rails
                            |---init.rb

This required the following changes:

In todo/lib/todo_lib.rb

%w{ models controllers views }.each do |dir|
  # Include the paths:
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/app/models
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/app/controllers
  # /Users/Me/Sites/myRailsApp/vendor/plugins/todo/app/views
  path = File.expand_path(File.join(File.dirname(__FILE__), '../app', dir))
  # We add the above path to be included when Rails boots up
  $LOAD_PATH << path
  ActiveSupport::Dependencies.load_paths << path
  ActiveSupport::Dependencies.load_once_paths.delete(path)
end

The change made above is in the line: path = File.expand_path(File.join(File.dirname(FILE), '../app', dir)). [Ignore the boldened 'FILE', this is an issue with the website].

Running script/server will render the index.html.erb page under todo/app/views/todos.

A: 

Looks like you want to build an "engine" plugin. Create "app" and "config" dirs in the root of your plugin dir (not under /lib). You can use app/views/ and app/controllers in your plugin as if it was a full featured Rails app. In config/routes.rb you should declare routes introduced by your engine.

See http://github.com/neerajdotname/admin_data for a decent example of what engine looks like.

hakunin
That worked great! What exactly is an engine plugin? What I want to do is compartmentalize my code so that I code less in the main application. In this case, I am taking one of my core classes and making a plugin out of it. Thanks for your help!
Dyba
Rails engine system allows you to wrap some part of rails app into a plugin or a gem. You can google around, but this railscast is a good starting point: http://railscasts.com/episodes/149-rails-engines
hakunin