Trying to implement a grid view with a one-to-many association

536 Views Asked by At

Image has a one-to-many association with Category:

# Category model:
has_many :images
# Image model:
has_one :category
# Images migration file:
t.references :category, index: true, foreign_key: true

I'm trying to implement a grid view using the wice_grid gem. This works but one line is failing. The following works in the index view:

g.column name: 'Category', attribute: 'category_id', auto_reload: true, html: {id: 'grid-cells'} do |image|
  image.category_id
end

But this displays the number/id of the category, while I want it to display its name. If I try image.category instead of image.category_id there's an error:

PG::UndefinedColumn: ERROR:  column categories.image_id does not exist
LINE 1: SELECT  "categories".* FROM "categories" WHERE "categories"."image_id...

How can I have it display the category name instead of the id of the category?

Controller method:

def index
  @images_grid = initialize_grid(Image,
  # include: :category  # Do I need this? Tried it with and without
  per_page: 40)
end

Update: After correcting the association and using in the view the code below, it works. Except for the filter function for this specific column. If I enter text to filter on, it reloads the table, but without applying the filter (all records are still displayed).

g.column name: 'Category', attribute: 'category_id', auto_reload: true, html: {id: 'grid-cells'} do |image|
  image.category.category unless image.category.nil?
end
3

There are 3 best solutions below

4
On BEST ANSWER

In the image model you should have belongs_to :category, not has_one. The association is the n-1, not 1-1.

On the second part of your problem - filtering the items by category name, I believe you need to use a custom filter:

g.column name: 'Category', attribute: 'images.category_id',
      custom_filter: Category.find(:all).map{|cat| [cat.id, cat.name]} do |image|
  image.category.name if image.category
end
1
On

It has many categories so you should do something like

image.categories.find(:id)

You need to get provide id for category as query image.categories will return a collection array of all the categories for the image

0
On

The other side of a has_many is a belongs_to. You need the image model to say:

belongs_to :category

The mnemonic I use to remember which is which is the "person and dog": A person has_many dogs, and a dog belongs_to an owner. Which one wears the "id_tag" on their collar? The dog. So the id column goes on the belongs_to model.