Вопрос

I am using Rails STI to model a complex domain. In a view, I am listing all subclasses with:

> <% StateDescription.subclasses.each do |state_description| %>   <li>
> <%= state_description.to_s %> </li> <% end %>

With the intent to eventually make each label of the subclass a link to the individual "index" page for just instances of that subclass.

This saves me from having to have a list of all possible subclasses myself (and updating it later if I add more).

However, I have noticed that only those subclasses I have actually loaded from the database show up in the list. If I say StateDescription.all, then all existing subclasses show up (but none that have no instances yet). If I instead ask for all of a particular subclass, then only that subclass show up.

I imagine this is part of the "lazy loading" I have heard about. Is it? It SEEMS like the problem is that if I don't grab a particular "type" from the database, even if I have a model for it, it may as well not exist?

Is there a way around this, or am I doomed to have to write out a link for every single subclass I create?

Edit:

On the console, if I type

StateDescription.subclasses.count

I get 0.

If I then do StateDescription.all and THEN StateDescription.subclasses.count, i get 14.

Это было полезно?

Решение

After doing some digging, it seems your hypothesis about subclasses not showing up due to lazy loading appears to be correct. Since you're running your application in development mode, all your classes are not loaded until they are specifically called. In production, you would not have this problem since everything is loaded at once and cached.

One way to get around this problem, according to this post, is to do something like this:

[Subclass1, Subclass2, Subclass3] if Rails.env == 'development'

You could put this at the top of your controller so that it loads the instant the controller classes is loaded, or in a before filter.

Другие советы

Not tested!

StateDescription.select("distinct type").map { |sd|  Kernel.const_get(sd.type) }

The easiest way to do this is eager_load! in development.

Something like:

<% Rails.application.eager_load! if Rails.env.development? %>
<% StateDescription.subclasses.each do |state_description| %>
  <li><%= state_description.to_s %> </li>
<% end %>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top