Sunday, January 25, 2009

Multiple Controllers

Often, a web site will have two (or more) types of users. For instance this blog has someone writing the blog and a number of people (hopefully) reading it. An online store will have someone administering or managing the site and a number of people making purchases from the site. In these cases, there will typically be multiple controllers, one for each function. The code shown here (essentially the same as our last bit of code for linking) doesn't really need multiple controllers, but is for display purposes only.

require 'rubygems'
require 'ramaze'

# This example is based on the previous "multiple pages" example.
# It has the same three methods (index, page1, and page2) but adds
# links on each page to the other two pages. For linking it uses
# the Ramaze Rs helper for linking within the same controller. The
# other item that is different is that instead of the content
# being in double quotes, we use the %{} form which is the same
# as the double quotes or as %Q{}. They just make it easier to
# include quotes in the string.
class MainController < Ramaze::Controller

# You can access it now with http://localhost:7000/
# This should output
# Hello, World from First Controller!
# in your browser and provide links to the other two pages
# as well as links to pages in the SecondController.
def index
%{
Hello, World from First Controller! <br/>
<a href="#{Rs(:page1)}">Page 1 MainController</a>
<a href="#{Rs(:page2)}">Page 2 MainController</a>
<br>
<a href="#{R(SecondController, :index)}">Index SecondController</a>
<a href="#{R(SecondController, :page1)}">Page 1 SecondController</a>
<a href="#{R(SecondController, :page2)}">Page 2 SecondController</a>
}
end

# You can access it now with http://localhost:7000/page1
# This should output
# "Page 1 from First Controller!"
# in your browser and provide links to the other two pages
# as well as links to pages in the SecondController.
def page1
%{
Page 1 from First Controller<br/>
<a href="#{Rs(:index)}">Hello world MainController</a>
<a href="#{Rs(:page2)}">Page 2 MainController</a>
<br>
<a href="#{R(SecondController, :index)}">Index SecondController</a>
<a href="#{R(SecondController, :page1)}">Page 1 SecondController</a>
<a href="#{R(SecondController, :page2)}">Page 2 SecondController</a>
}
end

# You can access it now with http://localhost:7000/page2
# This should output
# "Page 2 from First Controller!"
# in your browser and provide links to the other two pages
# as well as links to pages in the SecondController.
def page2
%{
Page 2 from First Controller<br/>
<a href="#{Rs(:index)}">Hello world MainController</a>
<a href="#{Rs(:page1)}">Page 1 MainController</a>
<br>
<a href="#{R(SecondController, :index)}">Index SecondController</a>
<a href="#{R(SecondController, :page1)}">Page 1 SecondController</a>
<a href="#{R(SecondController, :page2)}">Page 2 SecondController</a>
}
end
end

class SecondController < Ramaze::Controller

# The second controller will be accessed using "second"
# as in
# http://localhost:7000/second/index.
map '/second'

# You can access it now with http://localhost:7000/second
# This should output
# Hello, World from Second Controller!
# in your browser and provide links to the other two pages
# as well as links to pages in the FirstController.
def index
%{
Hello, World from Second Controller! <br/>
<a href="#{Rs(:page1)}">Page 1 SecondController</a>
<a href="#{Rs(:page2)}">Page 2 SecondController</a>
<br>
<a href="#{R(MainController, :index)}">Index MainController</a>
<a href="#{R(MainController, :page1)}">Page 1 MainController</a>
<a href="#{R(MainController, :page2)}">Page 2 MainController</a>
}
end

# You can access it now with http://localhost:7000/second/page1
# This should output
# "Page 1 from Second Controller!"
# in your browser and provide links to the other two pages
# as well as links to pages in the FirstController.
def page1
%{
Page 1 from Second Controller <br/>
<a href="#{Rs(:index)}">Hello world</a>
<a href="#{Rs(:page2)}">Page 2</a>
<br>
<a href="#{R(MainController, :index)}">Index MainController</a>
<a href="#{R(MainController, :page1)}">Page 1 MainController</a>
<a href="#{R(MainController, :page2)}">Page 2 MainController</a>
}
end

# You can access it now with http://localhost:7000/second/page2
# This should output
# "Page 2 from Second Controller!"
# in your browser and provide links to the other two pages
# as well as links to pages in the FirstController.
def page2
%{
Page 2 from Second Controller <br/>
<a href="#{Rs(:index)}">Hello world</a>
<a href="#{Rs(:page1)}">Page 1</a>
<br>
<a href="#{R(MainController, :index)}">Index MainController</a>
<a href="#{R(MainController, :page1)}">Page 1 MainController</a>
<a href="#{R(MainController, :page2)}">Page 2 MainController</a>
}
end
end

Ramaze.start




The first thing to note is the second class, once again derived from Ramaze::Controller called cleverly enough SecondController. The second controller uses the "map" function to tell how to access it. In this case, you would go to http://localhost:7000/second to get to the second controllers index method. This displays a page with the line "Hello World from Second Controller!" as well as links to the SecondController's pages and links back to all of the FirstController's pages. Links back to the FirstController's pages are made using the R helper for links to other controllers rather than the Rs helper for links within the same controller. It has the form:
<a href="#{R(MainController, :index)}">Index MainController</a>




In this case all we're doing is adding the controller as well as the method to the link.

Not too much else going on here, use the comments to post any questions you might have on the code.

5 comments:

  1. Hi, please continue this series - it is great to see working examples. For instance, I did not figure out up to this entry, how to correctly reference a controller in a R(). I had a little Ramaze application with 3 pages in one controller, but as soon as I tried to split it into three controllers, all blew up. In all the 35 years of my programming (FORTRAN, Pascal, C, Perl...) learned most of other good code (as described in "Software Tools" by Kerningan/Plauger. I am since one year a fan of Ruby for its possibility of really "esthetic" code. And I like the Ramaze framework. But due to its great flexibility I seldom find in the examples what I am looking for.

    ReplyDelete
  2. kittekat, Glad you enjoyed the posts and that the examples helped. I'm certainly planning on doing more along these lines.

    ReplyDelete
  3. Hi, Thanks for your series. This is the best way for me to learn Ramaze.

    ReplyDelete
  4. O man yes thanxs ! ... i have developed rails en ruby apps for years... but I got soo tired of the things you can't do with rails (wel "can't" just almost impossible :P ) ...

    Thanxs for this posts mate ! .. I hope you can keep it up :D

    ReplyDelete
  5. heldopslippers and nguye,

    Glad you both are enjoying the posts. Let me know of anything you'd like to see covered.

    ReplyDelete