Controllers with the same name in different namespaces

Discussion in 'Ruby/Rails' started by thijs, Jan 27, 2008.

  1. thijs

    thijs Member

    I've been having trouble getting a controller in a namespace with the same name as a controller in the root namespace. A simplified version of the code:
    ActionController::Routing::Routes.draw do |map|
      map.resources :editions
      map.namespace :organizer do |organizer|
        organizer.resources :editions
    class EditionsController < ApplicationController
      def index
    class Organizer::EditionsController < ApplicationController
      def index
    /editions shows the EditionsController#index action, but /organizer/editions shows the same EditionsController#index action. Rails does not seem to recognize the namespace in this url.

    This might well be a bug in Rails, we have some similar trouble running the specs in some situations. But this example does work well in Mongrel on our local machines.

    Litespeed consistently routes the namespaced url to the root controller. Do you have any idea what could be the cause of this problem?
  2. mistwang

    mistwang LiteSpeed Staff

    The only difference is that LiteSpeed only set a few Environment variable, not everyone in the shell, if you the route depends on some special environment variable, it must be set under "ruby rails" tab.
    For example, "HOME" must be set when use RESTful route.
  3. Grzegorz Derebecki

    Grzegorz Derebecki Well-Known Member

    I have the same problem :)

    When i do /opt/lsws/bin/lswsctrl restart

    my Movie:HomeController isn't used but it use HomeController

    But when i killall -9 ruby and litespeed start it from begining it start working ok.

    of corse doing /opt/lsws/bin/lswsctrl restart we have problem again :)

    PS. on apache i don't have problems with this :)
    Last edited: Jan 28, 2008
  4. Grzegorz Derebecki

    Grzegorz Derebecki Well-Known Member

    I find solution (i hope - becous errors can back ;-))

    I used Rails preload controllers

    if RAILS_ENV == 'production'
      require_dependency 'application'
      require_dependency 'movie/base'
      require_dependency 'admin/base'
      Dir.foreach( "#{RAILS_ROOT}/app/models" ) {|f| $logger.d "r #{f}"; silence_warnings{require_dependency f} if f =~ /\.rb$/}
      Dir.foreach( "#{RAILS_ROOT}/app/controllers/movie" ) {|f| $logger.d "r #{f}"; silence_warnings{require_dependency f} if f =~ /\.rb$/}
      Dir.foreach( "#{RAILS_ROOT}/app/controllers/admin" ) {|f| $logger.d "r #{f}"; silence_warnings{require_dependency f} if f =~ /\.rb$/}
      Dir.foreach( "#{RAILS_ROOT}/app/controllers" ) {|f| $logger.d "r #{f}"; silence_warnings{require_dependency f} if f =~ /\.rb$/}
    PS. $logger isn't working for rails 2.x
  5. mistwang

    mistwang LiteSpeed Staff

    Does $logger work for rails 2.x when WEBrick or mongrel is used?

    Another main difference of Ruby LSAPI is that it forks children processes off a process with initialized Rails framework, I am not sure it is the cause or not.
  6. Grzegorz Derebecki

    Grzegorz Derebecki Well-Known Member

    >> $logger
    => nil

    it don't even works in console :)
    This is just for controler, model, mailer. Maybe logger is initialized after environment, don't know :)

    Maybe forked children are problem..

    I don't found many simillar isuses only this one

    This error is very hard to reproduce becous sometimes it takes many request before it happends.
  7. mistwang

    mistwang LiteSpeed Staff

    I think it maybe related to ruby internal bugs, as I remember, there are bug related to popen() or other functions use fork() then exec(), if exec() failed, the forked children process does not shutdown properly.
  8. thijs

    thijs Member

    I've been doing a bit more research. I've traced the problem to constantize and finally to Object.module_eval

    If you replace your constantize method in active_support/lib/inflector.rb with this to get some logging:

    def constantize(camel_cased_word)
        unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
          raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
        result = Object.module_eval("::#{$1}", __FILE__, __LINE__)
        RAILS_DEFAULT_LOGGER.error("constantize '#{camel_cased_word}', result: '#{result}'") if camel_cased_word.ends_with?('Controller')
    You'll see the module_eval sometimes returns the class in the module, and sometimes it doesn't:

    My output when the processes have just been restarted is:

    constantize 'Organizer::EditionsController', result: 'Organizer::EditionsController'

    But later when the error occurs the log output is:

    constantize 'Organizer::EditionsController', result: 'EditionsController'

    This seems to be a problem in Ruby then?
  9. thijs

    thijs Member

    Thanks Grzegorz, you're suggestion seems to be fixing the issue. I've modified it a bit for Rails 2.0:

    controller_dir = "#{RAILS_ROOT}/app/controllers"
    Dir.foreach(controller_dir) { |f| silence_warnings { require_dependency("#{controller_dir}/#{f}") } if f =~ /\.rb$/ }
    Dir.foreach("#{controller_dir}/organizer") { |f| silence_warnings { require_dependency("#{controller_dir}/organizer/#{f}") } if f =~ /\.rb$/ }
  10. Grzegorz Derebecki

    Grzegorz Derebecki Well-Known Member

    at first require_dependency is bad, becous it is alias to load with meens that ruby will always reload our class and don't cache it.

    I think that i found some solutions about this here:

    I had movie model, and movie::home controller (movie/home) and i think this was problem:)

    thijs maby you have model organizer ? if yes just change namespace from organizer to organizers and it should works ok.
  11. mistwang

    mistwang LiteSpeed Staff

    I am not a RoR expert at all, but from a generic programming point of view, the route matching algorithm should try to match the longest path when possible, maybe change the routing configuration order can help.
  12. Grzegorz Derebecki

    Grzegorz Derebecki Well-Known Member

    i'm not RoR expert too but i think this is not routing foul.

    models in rails look like:
    class Foo < ActiveRecord:Base

    class FooController < ApplicationController

    but if we define namespace controller

    class Foo::TestController < ApplicationController

    we are in model namespace ;-) i think this is problem.

Share This Page