Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I've come across this data problem several times and have tried a few different strategies. I think the one I'm a biggest fan of, is the STI approach as mentioned by cicloon. Make sure you have a <code>type</code> column on your entry table.</p> <pre><code>class Blog &lt; ActiveRecord::Base # this is your generic association that would return all types of entries has_many :entries # you can also add other associations specific to each type. # through STI, rails is aware that a media_entry is in fact an Entry # and will do most of the work for you. These will automatically do what cicloon. # did manually via his methods. has_many :articles has_many :quotes has_many :media end class Entry &lt; ActiveRecord::Base end class Article &lt; Entry has_one :article_data end class Quote &lt; Entry has_one :quote_data end class Media &lt; Entry has_one :media_data end class ArticleData &lt; ActiveRecord::Base belongs_to :article # smart enough to know this is actually an entry end class QuoteData &lt; ActiveRecord::Base belongs_to :quote end class MediaData &lt; ActiveRecord::Base belongs_to :media end </code></pre> <p>The thing I like about this approach, is you can keep the generic Entry data in the entry model. Abstract out any of the sub-entry type data into their own data tables, and have a has_one association to them, resulting in no extra columns on your entries table. It also works very well for when you're doing your views:</p> <pre><code>app/views/articles/_article.html.erb app/views/quotes/_quote.html.erb app/views/media/_media.html.erb # may be medium here.... </code></pre> <p>and from your views you can do either:</p> <pre><code>&lt;%= render @blog.entries %&gt; &lt;!-- this will automatically render the appropriate view partial --&gt; </code></pre> <p>or have more control:</p> <pre><code>&lt;%= render @blog.quotes %&gt; &lt;%= render @blog.articles %&gt; </code></pre> <p>You can find a pretty generic way of generating forms as well, I usually render the generic entry fields in an <code>entries/_form.html.erb</code> partial. Inside that partial, I also have a</p> <pre><code>&lt;%= form_for @entry do |f| %&gt; &lt;%= render :partial =&gt; "#{f.object.class.name.tableize}/#{f.object.class.name.underscore}_form", :object =&gt; f %&gt; &lt;% end %&gt; </code></pre> <p>type render for the sub form data. The sub forms in turn can use <code>accepts_nested_attributes_for</code> + <code>fields_for</code> to get the data passed through properly.</p> <p>The only pain I have with this approach, is how to handle the controllers and route helpers. Since each entry is of its own type, you'll either have to create custom controllers / routes for each type (you may want this...) or make a generic one. If you take the generic approach, two things to remember. </p> <p>1) You can't set a <code>:type</code> field through update attributes, your controller will have to instantiate the appropriate <code>Article.new</code> to save it (you may use a factory here). </p> <p>2) You'll have to use the <code>becomes()</code> method (<code>@article.becomes(Entry)</code>) to work with the entry as an Entry and not a subclass.</p> <p>Hope this helps.</p> <p><strong>Warning, I've actually used Media as a model name in the past. In my case it resulted in a table called medias in rails 2.3.x however in rails 3, it wanted my model to be named Medium and my table media. You may have to add a custom Inflection on this naming, though I'm not sure.</strong></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload