Foreign relations in RoR models and forms


Update: Check out the HTTP Client article for more on how the below setup is later used to make life easier.

The work on SEO tools continues. The requirements for the current expansion is as follows and has to do with posting content to multiple wordpress blogs:

1.) We need to be able to upload a bunch of zipped html documents that will be randomly assigned to various blogs based on language. Article creation also needs to be done manually for complete control when it comes to publishing more important content to special blogs.

2.) In order for #1 to work we need an interface where we can add blogs, articles and Wordpress MU installations. Each article will belong to a blog and each blog will belong to an MU install.

3.) Each MU install needs to have a script that will receive the information we post from SEO tools.

Each of the above items is an article in itself but let’s start with #2 first, I will use the connection between article and blog in the following listings (the relation between MU installations and blogs works exactly the same way).

The WpArticle model:

class WpArticle < ActiveRecord::Base
  belongs_to :wp_site, :class_name => 'WpSite'
end

Easy enough, it belongs to a WpSite which brings us to the WpSite model:

class WpSite < ActiveRecord::Base
  has_many :wp_articles, :class_name => 'WpArticle', :foreign_key => :wp_site_id
  belongs_to :wp_mu, :class_name => 'WpMu'
end

Now comes the part where I had a harder time finding information about how to proceed, the add/edit WpArticle form:

<h1>New WP Article</h1>

<% form_for(@wp_article) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :subject %><br />
    <%= f.text_field :subject %>
  </p>
  <p>
    <%= f.label :content %><br />
    <%= f.text_area :content, :cols => 80, :rows => 20 %>
  </p>
  <p>
    <%= f.label :tags %><br />
    <%= f.text_field :tags %>
  </p>
  <p>
    <%= f.label :categories %><br />
    <%= f.text_field :categories %>
  </p>
  <p>
    <%= f.label :wp_site_id %><br />
    <%= collection_select(:wp_article, :wp_site_id, WpSite.all, :id, :name, {:prompt => true}) %>
  </p>
  <p>
    <%= f.label :country_code %><br />
    <%= f.text_field :country_code %>
  </p>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

<%= link_to 'Back', wp_articles_path %>

The main thing here is the collection_select call to get the drop down of blogs (wp_sites). The first argument refers to the table to insert into (wp_article in our case), the second is the name of the column that refers to the blog table (wp_sites). The third is what collection to use to create the select, in our case all blogs, finally we pass a hash of options. In our case the hash only contains a setting that will make a default first option to avoid accidentally selecting the first site in the drop down.

When we list articles we also want to display the name of the site each article belongs to, the wp_site_id won’t mean much to us:

<h1>Listing wp_articles</h1>

<table>
  <tr>
    <th>Subject</th>
    <th>Tags</th>
    <th>Categories</th>
    <th>Wp site</th>
    <th>Published</th>
    <th>Country Code</th>
  </tr>

<% for wp_article in @wp_articles %>
  <tr>
    <td><%=h wp_article.subject %></td>
    <td><%=h wp_article.tags %></td>
    <td><%=h wp_article.categories %></td>
    <td><%=h WpSite.find(wp_article.wp_site_id).name %></td>
    <td><%=h wp_article.published %></td>
    <td><%=h wp_article.country_code %></td>
    <td><%= link_to 'Show', wp_article %></td>
    <td><%= link_to 'Edit', edit_wp_article_path(wp_article) %></td>
    <td><%= link_to 'Destroy', wp_article, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New wp_article', new_wp_article_path %>

The main piece of code here is WpSite.find(wp_article.wp_site_id).name which will fetch the name of the site the article in question is connected to. We use the Active Record find method to do that. If simply passed a number it will by convention assume we want the record with the id of that number where the id column is also called simply ‘id’.

There are more examples of find usage in the next piece.

Related Posts

Tags: ,