I have a simple table being shown in ActiveScaffold. The table has three fields: an ID, a description, and a second ID which is a foreign key to another table. In the ActiveScaffold list view, I want to show the 'name' field from the related table rather than the foreign key value (an unhelpful ID number).
I have looked over the ActiveScaffold basic documentation, FAQ, and forum (as well as doing an SO search) with no luck. The AS API docs describe a boatload of functionality associated with ActiveRecord associations, but appear to have nothing on the basics of setting up these relationships.
How can I accomplish this?
After two days of searching and experimentation, I ended up figuring this out. Thought I'd post it just in case this is helpful to others.
I'll be using a Customer and Order example below (i.e. a Customer can have multiple Orders, and we want the Customer's name to show in the Order's ActiveScaffold view). The data structure is deliberately kept very simple.
First a couple of basic definitions for the below:
There are four basic steps to this process:
Here's a walkthrough:
Verify you’ve got a straightforward ActiveScaffold view working for the child. That process is outside the scope of this answer, but see the AS wiki for some straightforward instructions.
Add a foreign key in the child table. In Rails Migration-speak, this requires the creation of the tables, with the foreign ID field in the child table, and then “add_foreign_key [child table symbol], [parent table symbol]” In my case here’s the full migration:
class CustomerOrderAdd < ActiveRecord::Migration
def change
create_table(:customers, primary: :target_group_id) do |t|
t.column :full_name, :string, null: false
end
create_table(:orders, primary: :order_id) do |t|
t.column :customer_id, :int, null: false
t.column :order_desc, :string, null: false
end
add_foreign_key :orders, :customers
end
end
In the parent class, add has_many *child object symbol plural form*
In our example, this would be:
class Customer < ActiveRecord::Base
has_many :orders
end
In the child class, add belongs_to *parent object symbol singular form*
Again in our example, this leads to:
class Order < ActiveRecord::Base
belongs_to :target_group
. . .
end
In the child controller’s ActiveScaffold config block, add a column to your ActiveScaffold columns array that will display the related data from the parent class/table. Name this whatever you’d like to name it. Keep in mind you’ll need to use this in the remaining steps. In our example, this leads to the addition of :customer_name
in the columns array:
class OrdersController < ApplicationController
active_scaffold :order do |config|
config.label = 'Customer Orders'
config.list.sorting = [{customer_id: :asc}]
config.list.per_page = 30
config.columns = [:id, :order_desc, :customer_name]
end
end
To speed things up a bit, tell ActiveScaffold to load parent table data as soon as possible. In our example, this leads to the following addition to the child controller's ActiveScaffold config area:
config.columns[:customer_name].includes = :customer]
Add a function in your child model named exactly the same as the new column name you added to the ActiveScaffold columns array. In this function, type out the related class/table name with a dot at the end, then the property/column name you want to actually show. In the example, this looks like:
def customer_name
customer.full_name
end
Hit your ActiveScaffold index view for the child class/table. Your value should now be in place.