Organize models in subfolders

46 views
Skip to first unread message

Maurizio De Santis

unread,
Feb 24, 2017, 10:49:10 AM2/24/17
to Ruby on Rails: Core
[From the issue I opened about it: https://github.com/rails/rails/issues/28152]

I don't know if this is more a bug report or a feature request, or even an SO question :flushed: anyway:


I have a model Activity which has a lot of sti types, so a lot of related class files. I would like to organize them into app/models/activities, in order to separate them from the other models. I can actually accomplish it using config.eager_load_paths += %W(#{config.root}/app/models/activities) directive, but then in development mode the following exception is raised:

ArgumentError: A copy of SubFolderModel has been removed from the module tree but is still active!

I guess the reason is that app/models/subfolder conflicts with app/models autoload. Anyway, is there a way to organize models using different directories?

Steps to reproduce

  • Create an app/models subfolder
  • Put some models inside
  • Add config.eager_load_paths += %W(#{config.root}/app/models/subfolder) to config/application.rb
  • Start the application in development mode

Expected behavior

Everything works fine

Actual behavior

Sometimes the following exception is raised:

ArgumentError: A copy of SubFolderModel has been removed from the module tree but is still active!

System configuration

Rails version: 5.0.1

Ruby version: 2.4.0

Allen Madsen

unread,
Feb 24, 2017, 11:48:51 AM2/24/17
to rubyonra...@googlegroups.com
I believe everything under app/models is loaded by default, so you shouldn't need to add a subdirectory.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

Jason Fleetwood-Boldt

unread,
Feb 24, 2017, 12:02:18 PM2/24/17
to rubyonra...@googlegroups.com
I think this question might be better for Rails-talk or Stack Overflow, as Rails-core is designated for discussion of the core itself.

However, I will answer it anyway....

Unless I'm mistaken, OP is wanting to segregate his models into subfolders.

"The Rails way" philosophy on this, which I will voice objection too as someone who works primarily on very large apps, is typical to optimize for small apps and easy-of-entry into the ecosystem but not particularly optimized for larger apps.

On a larger apps, you could have hundreds and hundreds of models. Separating into subfolders is perfectly appropriate.

OP -- I think perhaps all you need is to namespace your models themselves. For example, we have a folder in app/models called platform (a generic name, I know)

All of the models inside of app/models/platform are namespaced using

Platform::

so we have a model called Platform::Block (the file name is app/models/platform/platform/block.rb)

You can define this using

class Platform::Block < ActiveRecord::Base

# your class code here
end


alternatively, another Ruby syntax for the same thing is

module Platform
class Block < ActiveRecord::Base
# your class code here
end
end


I believe the only way to put models into subfolder is to rename them using namespaces. Renaming is a good idea, but of course affects things like all the relationships and STI ('type' column in a polymorphic implementation), which all have to be renamed. (So it's not quite as simply as dragging them into a folder)

A foreign key to this model also usually then needs a class_name on it, except I think in cases where the foreign key is coming from another model that is also in the same namespace.

-Jason





> On Feb 24, 2017, at 11:48 AM, Allen Madsen <allen.c...@gmail.com> wrote:
>
> I believe everything under app/models is loaded by default, so you shouldn't need to add a subdirectory.
>
> Allen Madsen
> http://www.allenmadsen.com
>
> On Fri, Feb 24, 2017 at 10:49 AM, Maurizio De Santis <desantis...@gmail.com> wrote:
> [From the issue I opened about it: https://github.com/rails/rails/issues/28152]
>
> I don't know if this is more a bug report or a feature request, or even an SO question anyway:
>
>
> I have a model Activity which has a lot of sti types, so a lot of related class files. I would like to organize them into app/models/activities, in order to separate them from the other models. I can actually accomplish it using config.eager_load_paths += %W(#{config.root}/app/models/activities) directive, but then in development mode the following exception is raised:
>
>
> ArgumentError: A copy of SubFolderModel has been removed from the module tree but is still active!
>
> I guess the reason is that app/models/subfolder conflicts with app/models autoload. Anyway, is there a way to organize models using different directories?
>
>
> Steps to reproduce
>
> • Create an app/models subfolder
> • Put some models inside
> • Add config.eager_load_paths += %W(#{config.root}/app/models/subfolder) to config/application.rb
> • Start the application in development mode
> Expected behavior
>
>
> Everything works fine
>
>
> Actual behavior
>
>
> Sometimes the following exception is raised:
>
>
> ArgumentError: A copy of SubFolderModel has been removed from the module tree but is still active!
>
> System configuration
>
>
> Rails version: 5.0.1
>
> Ruby version: 2.4.0
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> Visit this group at https://groups.google.com/group/rubyonrails-core.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
----

Jason Fleetwood-Boldt
te...@datatravels.com
http://www.jasonfleetwoodboldt.com/writing

If you'd like to reply by encrypted email you can find my public key on jasonfleetwoodboldt.com (more about setting GPG: https://gpgtools.org)


Maurizio De Santis

unread,
Feb 24, 2017, 12:47:22 PM2/24/17
to rubyonra...@googlegroups.com
I think this question might be better for Rails-talk or Stack Overflow, as Rails-core is designated for discussion of the core itself.

Uh, sorry!

So you say I could do for example something like:

# app/models/activity.rb
class Activity < ApplicationRecord
end

# app/models/activity/activity_1.rb
class Activity
  class Activity1 < Activity
  end
end

And get rid from
ArgumentError: A copy of SubFolderModel has been removed from the module tree but is still active!

errors? It would be suitable for me!

--

Maurizio De Santis

> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com.
> To post to this group, send email to rubyonrails-core@googlegroups.com.

> Visit this group at https://groups.google.com/group/rubyonrails-core.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com.
> To post to this group, send email to rubyonrails-core@googlegroups.com.
----

Jason Fleetwood-Boldt
te...@datatravels.com
http://www.jasonfleetwoodboldt.com/writing

If you'd like to reply by encrypted email you can find my public key on jasonfleetwoodboldt.com (more about setting GPG: https://gpgtools.org)


--
You received this message because you are subscribed to a topic in the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rubyonrails-core/krboJIieoXk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rubyonrails-core+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.

Jason Fleetwood-Boldt

unread,
Feb 24, 2017, 1:08:27 PM2/24/17
to rubyonra...@googlegroups.com

not a Class within a Class, a Class within a Module, like so:

module Activity
  class Activity1 < ActivityBase
  end
end

or, alternatively...

class Activity::Activity1 < ActivityBase


Note in my example I renamed your base class to "ActivityBase" because I believe if you continue to reference it as simply "Activity" you'll run into namespace problems.

-Jason 


On Feb 24, 2017, at 12:46 PM, Maurizio De Santis <desantis...@gmail.com> wrote:

# app/models/activity/activity_1.rb
class Activity
  class Activity1 < Activity
  end
end

Maurizio De Santis

unread,
Feb 27, 2017, 12:38:43 PM2/27/17
to rubyonra...@googlegroups.com
This seems to break the STI :-( Activity1 is not found as an STI class


--

Maurizio De Santis

Jason Fleetwood-Boldt

unread,
Feb 27, 2017, 5:05:30 PM2/27/17
to rubyonra...@googlegroups.com

Yes, as I had explained in my previous email, you will absolutely need to rename the objects in the 'type' column when using STI/polymorphism. There are several other things to consider as well when making this kind of an object name change. 

You can do this directly in SQL (it would be fastest, and works around the impossibility of loading these records). I would suggest doing it in SQL in a migration.

-Jason


You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

Maurizio De Santis

unread,
Mar 1, 2017, 1:25:45 PM3/1/17
to rubyonra...@googlegroups.com
It works!!! In many years I've been working with Rails I wasn't aware about this way to organize models. Thank you!

For the namespace instead of defining an Activity module I just used the model Activity:

# app/models/activity.rb
class Activity < ApplicationRecord
end

# app/models/activity/activity_1.rb
class Activity::Activity1 < Activity
end

And it works like a charm! Thank you!


--

Maurizio De Santis

To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscribe@googlegroups.com.

To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

If you'd like to reply by encrypted email you can find my public key on jasonfleetwoodboldt.com (more about setting GPG: https://gpgtools.org

Tom Prats

unread,
Mar 1, 2017, 3:55:27 PM3/1/17
to rubyonra...@googlegroups.com
I'd still be interested in how to make this possible without name-spacing the models. With STI the type column is more presentable to an end user without it. Activity::Something vs. Something. It'd be nice if this were possible (if not the default).

Thanks,
Tom


--

Maurizio De Santis

To unsubscribe from this group and all its topics, send an email to rubyonrails-co...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

If you'd like to reply by encrypted email you can find my public key on jasonfleetwoodboldt.com (more about setting GPG: https://gpgtools.org

--
You received this message because you are subscribed to a topic in the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rubyonrails-core/krboJIieoXk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rubyonrails-co...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-co...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages