Controllers with the same name in different namespaces

#1
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:
Code:
ActionController::Routing::Routes.draw do |map|

  map.resources :editions

  map.namespace :organizer do |organizer|
    organizer.resources :editions
  end

end

class EditionsController < ApplicationController

  def index
  end

end

class Organizer::EditionsController < ApplicationController

  def index
  end

end
/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?
 

mistwang

LiteSpeed Staff
#2
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
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:
#4
I find solution (i hope - becous errors can back ;-))

I used Rails preload controllers

Code:
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$/}
 
end
PS. $logger isn't working for rails 2.x
 

mistwang

LiteSpeed Staff
#5
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
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.

>> $logger
=> nil

it don't even works in console :)
http://wiki.rubyonrails.org/rails/pages/logger
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 http://www.ruby-forum.com/topic/125392

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

mistwang

LiteSpeed Staff
#7
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
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:

Code:
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!"
    end
    
    result = Object.module_eval("::#{$1}", __FILE__, __LINE__)
    RAILS_DEFAULT_LOGGER.error("constantize '#{camel_cased_word}', result: '#{result}'") if camel_cased_word.ends_with?('Controller')
    result
  end
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
Thanks Grzegorz, you're suggestion seems to be fixing the issue. I've modified it a bit for Rails 2.0:

Code:
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
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:

http://peat.wordpress.com/2006/06/30/watch-your-namespace/

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.
 

mistwang

LiteSpeed Staff
#11
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
i'm not RoR expert too but i think this is not routing foul.

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


controllers
class FooController < ApplicationController
end


but if we define namespace controller

class Foo::TestController < ApplicationController
end

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