user1876128
user1876128

Reputation: 91

ruby on rails 4 foreign key and association to access another table's attributes

The question is how can I list all the assets associated to each Project?

Here is what I have so far: I have a project model and asset model. a project can have many assets (uploaded by Carrier wave)

here is the project.rb

class Project < ActiveRecord::Base
    validates :title, length: { maximum: 150 } ,uniqueness: true, presence: true
    has_many :assets
end

and here is the asset.rb

class Asset < ActiveRecord::Base
    mount_uploader :attachment, AttachmentUploader 
    belongs_to:project
end

In my index method in project_controller.rb ,I have the following instance variables:

class ProjectsController < ApplicationController
    def index
    @projects = Project.all
    @assets = Asset.all
     end

  def project_params
      params.require(:project).permit(:title,assets_attributes: [:id,:project_id,:attachment])
  end
end

and this is the view, index.html.erb which lists all the assets not the one associated with the project

<% @projects.each do |project| %>
    <td><%= project.title %></td>
        <% @assets.each do |asset| %>
            <td><%= asset.attachment.size %></td> 
         <% end %>
<% end %>

Upvotes: 0

Views: 1206

Answers (1)

Robin
Robin

Reputation: 21884

Your view should look like this:

<% @projects.each do |project| %>
    <td><%= project.title %></td>
    <% project.assets.each do |asset| %>
        <td><%= asset.attachment.size %></td> 
    <% end %>
<% end %>

Don't forget to remove @assets = Asset.all from your controller, and think about adding pagination.

Also, to avoid N+1 queries in your view, you can do

@projects = Project.includes(:assets) # you dont need .all, I think it's deprecated in rails 4 when you use it this way

in your controller. That will load all the needed projects in 1 query.

And if you only need the size attribute from assets, you can do this to make it more efficient:

@projects = Project.includes(:assets).select('projects.*, assets.size').references(:assets)

Upvotes: 1

Related Questions