Контроллер Rails 3 и вложенные папки модели

Я пишу приложение Rails 3.2.6. Я хочу разделить свои контроллеры и модели на подпапки, чтобы мой код оставался чистым. Я убедился, что модель и имя ее подкаталога не совпадают. Однако я обнаружил, что код дает сбой, если имя подкаталога контроллера и имя подкаталога модели совпадают.

Следующая структура приложения работает нормально:

test
  app
    controllers
      postcnt
        posts_controller.rb
    models
      postmdl
        post.rb

но следующая структура не делает:

test
  app
    controllers
      postnsp
        posts_controller.rb
    models
      postnsp
        post.rb

Когда я вызываю URL:

http://localhost:3000/postnsp/posts

Я получаю ошибку 500 с сообщением:

LoadError in Postnsp::PostsController#index
Expected /Users/dev/code/test/app/models/postnsp/post.rb to define Postnsp::Post

В приведенных выше примерах я последовал совету здесь, чтобы исключить пространство имен модели: -submodul">Rails: элегантный способ структурировать модели в подпапки без создания подмодулей

и добавил

config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]

в мой файл application.rb

Для второго (неудачного) примера соответствующие файлы выглядят следующим образом:

пост.рб:

class Post < ActiveRecord::Base
  attr_accessible :content, :name
end

posts_controller.rb:

class Postnsp::PostsController < ApplicationController
  def index
  @posts = Post.all

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @posts }
  end
end

маршруты.rb:

Test::Application.routes.draw do
  namespace :postnsp do resources :posts end

Кто-нибудь может объяснить, почему подкаталоги не могут быть одинаковыми? Я предполагаю, что это как-то связано с созданием модуля postnsp для posts_controller.rb, но я не могу понять, почему это препятствует созданию модели. Я хотел бы иметь согласованность в именовании структуры каталогов как в папках контроллера, так и в папках модели, если мне это потребуется.


person benmac    schedule 04.07.2012    source источник
comment
Я думаю, что это должно быть class Postnsp::Post < ActiveRecord::Base и в файле модели .rb. (префикс Postnsp)   -  person Zabba    schedule 04.07.2012
comment
Смотрите мой ответ Драйкену ниже. Оба приведенных выше примера не имеют моделей с пространством имен — один работает, другой нет. Я не хочу менять модель, я хочу знать, что в конструкции рельсов мешает работе второго варианта.   -  person benmac    schedule 04.07.2012
comment
Вероятно, из-за того, как работает автоматическая загрузка в Ruby. Вероятно, это одна из областей, где вы боретесь с рельсами (хорошо это или плохо, без комментариев!). Но почему вы хотите разделить на каталоги? Чего это вам дает, кроме ощущения чистоты? (Я убедился, что имя модели и ее подкаталога не совпадают. => вы уже однажды сражались с рельсами, ожидайте большего!)   -  person Zabba    schedule 04.07.2012
comment
Спасибо. Я переношу приложение с Rails 2 на Rails 3, и оно имеет около 70 контроллеров и 70 моделей, поэтому плоская структура каталогов становится неподдерживаемой. Обе структуры каталогов, которые я показал выше, отлично работают в Rails 2, но в Rails 3 вторая не работает. Прежде чем приступить к изменению приложения, я действительно хочу понять, что изменилось, и убедиться, что я не упускаю никаких простых исправлений, которые помогут мне сохранить текущую структуру.   -  person benmac    schedule 04.07.2012
comment
К сожалению, я не нашел другого решения для этого, но просто обратите внимание, что ваше исправление переименования подпапки модели сработало для меня. Я просто переименовал в [subfolder]_models, изменил путь автозагрузки, и все заработало нормально.   -  person shalott    schedule 20.11.2012


Ответы (1)


Поскольку Post находится в каталоге postnsp, ожидается, что модель также будет ограничена пространством имен.

Попробуйте изменить Post на Postnsp::Post < ActiveRecord::Base

ОБНОВЛЕНИЕ

Хорошо, я попробовал приложение, чтобы сделать именно то, что вы сказали, и я думаю, что знаю, что не так... Поскольку вы находитесь внутри контроллера с пространством имен, когда вы используете Post, он фактически ищет Postnsp::Post, чтобы использовать базовый класс, который вы должен использовать ::Post и тогда у меня все заработало.

Надеюсь это поможет.

person Draiken    schedule 04.07.2012
comment
Спасибо за ответы, но я не хочу использовать пространство имен для моделей. Я не хочу, чтобы таблицы базы данных назывались postnsp_posts (или приходилось переопределять имя таблицы в каждой модели) только в силу того факта, что я структурировал свое приложение в виде каталогов. В других сообщениях (в том числе упомянутом в моем вопросе) объясняется, как избежать моделей пространства имен, и это отлично работает в консоли Rails, но в них не рассматривается, как контроллеры в подпапках могут вызывать эти модели без пространства имен. Я действительно хочу знать, почему первая структура каталогов в моем вопросе работает, а вторая - нет. - person benmac; 04.07.2012
comment
Я обновил свой код posts_controller.rb, чтобы использовать @post = ::Post.all, и это не имело значения (я согласен, что так и должно быть). Как я упоминал в комментариях к моему первоначальному вопросу, оба примера в моем вопросе работают с Rails 2. Мне действительно хотелось знать, что было изменено в ApplicationController в Rails 3 (и где), чтобы подразумевать пространство имен контроллера. Даже если я смогу заставить работать соглашение ::Post, я не хочу менять каждую ссылку в моем коде на синтаксис ::, чтобы он работал с Rails 3. Я хочу знать, есть ли простое исправление или конфигурация чтобы обойти проблему. - person benmac; 04.07.2012
comment
Проблема заключается в постоянном поиске, который использует Rails. По умолчанию поиск основан на текущем module. Я не уверен, что вы можете возиться с этим. Я никогда не использовал модели в папках специально из-за этих ошибок и несоответствий, которые могут возникнуть внутри самих рельсов. - person Draiken; 05.07.2012