ruby-on-rails-4activerecordtwitter-bootstrap-3nested-includes

Rails 4 includes multiple has_many and belongs_to index.html.erb


How would I handle a belong_to with the following include. Instead of displaying the product_colour_id id like to show the associated colour (Update:Solved this part below). The product_colour_id is in the Product table and matches the corresponding Product_colour id.

Its the case of two or more has_many associations that i cant work out. Can it be done?

app/controller/home_controller.rb

  class HomeController < ApplicationController
  def index
    products = Product.last(5)
    product_ids = products.map(&:id)   
    @product_colour_ids = products.map(&:product_colour_id)
    @allproduct_colours = ProductColour.all 
    @product_colour_map = ProductColour.find(@product_colour_ids)   
    @product_images = Product.includes(:product_images)
                    .where(product_images: {product_id: product_ids, :default_image => true})
  end
end

/app/views/home/index.html.erb

<% @product_images.each do |pd| %>
          <%= content_tag :div, :class => "col-md-3 col-sm-6 hero-feature" do %>
          <% pd.product_images.each do |i| %>
              <div class="thumbnail">
                <%= image_tag (i.product_image(:medium)) %>
          <% end %> </div>
          <div class="caption">
            <h3><%= pd.product_name %></h3>
            <p><%= pd.product_description %></p>
            <p> <%= pd.product_colour_id %></p>
          </div>
          <% end %>
      <% end %>
    </div>

I'm having difficulty finding examples of multiple has_many includes. I assume there is a very straight forward pattern to it but cant work it out from apidock or api.rubyonrails.org. The problem i'm having is adding the Supply_company which is a has_many :through relationship to the one I already have with the product_image include.

Thankyou in advance for your advise

Update I have worked out how to display the belongs_to... feeling a little dumb on that as it was very easy just needed some time to think

 <% pd.product_images.each do |pd| %>
   <p> <%= pd.product_colour.product_colour %></p>
 <% end %>

/app/models/product.rb

class Product < ActiveRecord::Base
  belongs_to :product_type
  belongs_to :product_category
  belongs_to :product_colour
  belongs_to :product_size

  has_many :product_supply_companies, :foreign_key => 'product_id'
  accepts_nested_attributes_for :product_supply_companies, :allow_destroy => true
  has_many :supply_companies, :through => :product_supply_companies
  accepts_nested_attributes_for :supply_companies

  has_many :product_images, dependent: :destroy, :foreign_key => 'product_id'
  accepts_nested_attributes_for :product_images, :allow_destroy => true
end

app/models/product_supply_company.rb

class ProductSupplyCompany < ActiveRecord::Base
  belongs_to :product
  belongs_to :supply_company

 # accepts_nested_attributes_for :supply_company
 # accepts_nested_attributes_for :product

end

app/models/supply_company.rb

class SupplyCompany < ActiveRecord::Base

  has_many :products, :through => :product_supply_companies
  has_many :product_supply_companies, :foreign_key => 'supply_company_id'

  accepts_nested_attributes_for :products
  accepts_nested_attributes_for :product_supply_companies, :allow_destroy => true

end

app/models/product_colour.rb

class ProductColour < ActiveRecord::Base
  has_many :products
end

Database Schema

 create_table "product_categories", force: true do |t|
    t.string   "product_category"
    t.string   "product_category_description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "product_colours", force: true do |t|
    t.string   "product_colour"
    t.string   "product_colour_description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "product_images", force: true do |t|
    t.integer  "product_id",                 null: false
    t.datetime "created_at",                 null: false
    t.datetime "updated_at",                 null: false
    t.string   "product_image_file_name"
    t.string   "product_image_content_type"
    t.integer  "product_image_file_size"
    t.datetime "product_image_updated_at"
    t.boolean  "default_image"
  end

  create_table "product_sizes", force: true do |t|
    t.string   "product_size"
    t.string   "product_size_description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "product_supply_companies", force: true do |t|
    t.integer  "product_id"
    t.integer  "supply_company_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "product_types", force: true do |t|
    t.string   "product_type"
    t.string   "product_type_description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "products", force: true do |t|
    t.string   "product_name"
    t.text     "product_description"
    t.integer  "product_type_id"
    t.integer  "product_category_id"
    t.string   "product_colour_id"
    t.integer  "product_size_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

Solution

  • @products = Product.includes(:product_images, :colour, :supply_companies)
                       .where(product_images: {product_id: product_ids, :default_image => true})
                       .select('products.*, product_colours.product_colour')
    

    this the query with all associations.

    index.html.erb

    <% @products.each do |pd| %>
        <%= content_tag :div, :class => "col-md-3 col-sm-6 hero-feature" do %>
        <% pd.product_images.each do |i| %>
            <div class="thumbnail">
              <%= image_tag (i.product_image(:medium)) %>
            </div>
        <% end %> 
        <div class="caption">
          <h3><%= pd.product_name %></h3>
          <p><%= pd.product_description %></p>
          <p><%= pd.product_colour %></p>
        </div>
        <% end %>
    <% end %>
    

    Product.rb

    belongs_to :colour, class: 'ProductColor', foreign_key: 'product_colour_id'