Modele w subfolderach

Witam,

Mam problem z umieszczeniem modeli w subfolderach. Mam 2 wersje - jedna działa w konsoli, przez kontrolery itd, druga w testach

Wersja 1 (działająca w konsoli, kontrolerach)
ścieżka: /app/models/activity/user.rb

class Activity::User < Version end

  • Version to klasa z Paper Trail

Wtedy rspec wyrzuca:

LoadError: Expected /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/activity/user.rb to define Activity::User
spec_helper.rb - https://gist.github.com/1210936
Testu nie wrzucam, bo błąd jest nawet przy zwykłym:

[code=ruby]#/spec/models/activity/user_spec.rb
require ‘spec_helper’

describe Activity::User do
end[/code]
Wersja 2 (działająca w rspecu)
ścieżka: /app/models/activity/activity_user.rb

class Activity::User < Version end
Wtedy aplikacja wyrzuca:

ruby-1.9.2-p180 :005 > Activity::User NameError: uninitialized constant Activity::User from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/inflector/methods.rb:124:in `block in constantize' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/inflector/methods.rb:123:in `each' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/inflector/methods.rb:123:in `constantize' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/core_ext/string/inflections.rb:43:in `constantize' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/paper_trail-2.3.2/lib/paper_trail/has_paper_trail.rb:53:in `has_paper_trail' from /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/user.rb:28:in `<class:User>' from /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/user.rb:10:in `<top (required)>' from (irb):5 from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-3.1.0.rc4/lib/rails/commands/console.rb:45:in `start' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-3.1.0.rc4/lib/rails/commands/console.rb:8:in `start' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-3.1.0.rc4/lib/rails/commands.rb:40:in `<top (required)>' from script/rails:6:in `require' from script/rails:6:in `<main>'
Edit:
oczywiście appka szuka modeli w podfolderach:

#/config/application.rb config.autoload_paths += Dir["#{config.root}/app/models/**/"]

To chyba musi być jakiś błąd w rspecu (lub, co bardziej prawdopodobne :D, w mojej konfiguracji). Rozwiązanie 1 jest prostsze, działa tak jak powinno… tylko testy się nie chcą wykonywać :confused:

Nie mogę znaleźć żadnego rozwiązania w sieci, ktoś z was może napotkał kiedyś podobny problem?

A spróbuj wersję 1 z taką definicją w pliku:

module Activity # lub 'class Activity' jeśli to klasa class User < Version end end

:frowning: Dalej ten sam błąd

Jest tak:

W app/models/user.rb mam:

class User < ActiveRecord::Base has_paper_trail class_name: 'Activity::User' end
W app/models/activity/user.rb mam:

module Activity class User < Base # ... end end
W app/models/activity/base.rb :

[code=ruby]require ‘activity_helper’

module Activity
class Base < Version
def self.inherited(child)
child.send :include, ActivityHelper
end
end
end[/code]
Teraz (kiedy Activity::User dziedziczy po Base a nie po Version) rspec wyrzuca:

Exception encountered: #<LoadError: Expected /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/activity/base.rb to define Activity::Base> backtrace: /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:490:in `load_missing_constant' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:181:in `block in const_missing' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:179:in `each' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:179:in `const_missing' /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/activity/company.rb:2:in `<module:Activity>' /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/activity/company.rb:1:in `<top (required)>' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `require' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `block in require' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:225:in `load_dependency' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/dependencies.rb:237:in `require' /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/spec/spec_helper.rb:74:in `block (2 levels) in <top (required)>' /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/spec/spec_helper.rb:74:in `each' /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/spec/spec_helper.rb:74:in `block in <top (required)>' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork.rb:69:in `call' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork.rb:69:in `block in exec_each_run' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork.rb:69:in `each' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork.rb:69:in `exec_each_run' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:12:in `block in run' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/forker.rb:21:in `block in initialize' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/forker.rb:18:in `fork' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/forker.rb:18:in `initialize' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:9:in `new' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:9:in `run' /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/spork-0.9.0.rc9/lib/spork/server.rb:48:in `run' /home/kzalewski/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1558:in `perform_without_block' /home/kzalewski/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1518:in `perform' /home/kzalewski/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1592:in `block (2 levels) in main_loop' /home/kzalewski/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1588:in `loop' /home/kzalewski/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/drb/drb.rb:1588:in `block in main_loop'
Kod w konsoli działa normalnie, nowe wersje (paper trail) się zapisuję, wszystko pięknie.

A masz app/models/activity.rb z modułem w środku?

Nie, nie mam w ogóle modelu Activity (app/models/activity.rb)

Spróbuj dodać taki plik z samą definicją modułu:

module Activity end

o_O działa! :smiley: Dzięki!

Mógłbyś proszę powiedzieć dlaczego musi istnieć taki pusty plik z modułem? Jakaś czarna magia Railsów?

Albo bug, albo regresja, albo nieudokumentowana zmiana w API: dawno dawno temu (nie pamiętam czy w 1.2.x czy 2.x) namespace’owanie modeli działało rewelacyjnie.

Wyrzuć to: config.autoload_paths += Dir["#{config.root}/app/models/**/"] .

Jeśli masz w autoload_path katalog A i model B::C to bedzię on szukał pliku a/b/c.rb. To co dorzuciłeś powoduje, że będzie szukał także a/b/b/c.rb . Nie trzeba tego dodawać (powiedziałbym, że nie powinieneś był nawet). Do autoload_paths dodajesz korzeń od któego mają być szukane, bez zagnieżdżeń a twoja wersja dodaje zagnieżdżenia.

Plik activity.rb nie jest wymagany. Autoloading potrafi sam stwierdzić, że jest moduł potrzebny z faktu, że jest katalog o odpowiedniej naziwe.

Nie polecałbym na przyszłość rozwiązania radarka:

module Activity # lub 'class Activity' jeśli to klasa class User < Version end end
Pisanie w ten sposób powoduje, że jeśli miałbyś plik activity w stylu:

module Activity def self.table_name_prefix 'activity_' end end
to nie zostanie on załadowany bo moduł jest znaleziony i nie idzie const_missing zatem nie trigerujemy autoloadingu, który by wczytał ten plik. W ten sposób Activity::User miałoby źle zdefiniowany table_name (bez prefiksu).

Kiedyś napiszę o tym wszystkim rant…

+1, nie zauważyłem w pierwszym poście tej linijki do autoload_paths. Co do app/models/activity.rb, to z reguły załatwia to sprawę jak są jakieś problemy z autoloadem, ale tak jak napisał Robert, powinno działać też bez tego.

No dalej jest coś nie tak. Wyrzuciłem autoload_path,

[code=ruby]# /app/models/activity/user.rb
module Activity
class User < Base

end
end[/code]
zamieniłem na

[code=ruby]# /app/models/activity/user.rb
class Activity::User < Activity::Base

end[/code]
I dalej otrzymuję ten sam błąd (#<LoadError: Expected (…) to define (…)>)

Po dodaniu activity.rb (/app/models) z pustym modułem Activity wszystko jest OK

Nie powiedziałeś nam tylko 1 rzeczy: Jaka wersja Rails ?

Jak to nie? :wink: 3.1.rc4

[quote]ruby-1.9.2-p180 :005 > Activity::User
NameError: uninitialized constant Activity::User
from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/inflector/methods.rb:124:in block in constantize' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-[b]3.1.0.rc4[/b]/lib/active_support/inflector/methods.rb:123:ineach’
from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-3.1.0.rc4/lib/active_support/inflector/methods.rb:123:in constantize' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/activesupport-[b]3.1.0.rc4[/b]/lib/active_support/core_ext/string/inflections.rb:43:inconstantize’
from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/paper_trail-2.3.2/lib/paper_trail/has_paper_trail.rb:53:in has_paper_trail' from /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/user.rb:28:inclass:User
from /media/Multimedia/Projekty/Sekwencja/Prokliencki/prokliencki/app/models/user.rb:10:in <top (required)>' from (irb):5 from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-[b]3.1.0.rc4[/b]/lib/rails/commands/console.rb:45:instart’
from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-3.1.0.rc4/lib/rails/commands/console.rb:8:in start' from /home/kzalewski/.rvm/gems/ruby-1.9.2-p180@prokliencki/gems/railties-[b]3.1.0.rc4[/b]/lib/rails/commands.rb:40:in<top (required)>’
from script/rails:6:in require' from script/rails:6:in'[/quote]
:lol:

Dzisiaj spróbuję zrobić upgrade do 3.1 stable i sprawdzę czy błąd zniknął

No tak. Spróub ewentualnie też downagrade do 3.0.10 by sprawdzić czy błąd zniknie.