Search code examples
ruby-on-railslink-to

passing product info from one view to another


My 'Office' view displays the office products found in the product database. More than one product is displayed within this view so i want users to be able to click on an office product which goes to the 'show' view that displays just that products details.

My store controller looks like this: -

class StoreController < ApplicationController  
  def index
    @products = Product.all
  end

  def show
    @products = Product.find_by(:id)
    if @products.nil?
      redirect_to action: :index
    end
  end
end

The link_to code within the Office view looks like this: -

<p class="showArticle"><%= link_to 'Show Article', store_show_path %></p>

The code for the product in the show view looks like this: -

<%= @products.title(:id) %>

The office products are displayed properly within the office view. When the products link_to is clicked, the browser redirects using the action: :index as @products.nil? is evaluated as true.

How should I be passing this products details into the show view so that the products details are seen?

The following is my routes.rb file:-

Easygifts::Application.routes.draw do
  get "store/index"
  get "store/writing"
  get "store/office"
  get "store/time"
  get "store/home"
  get "store/wellness"
  get "store/travel"
  get "store/bags"
  get "store/leisure"
  get "store/show"
  resources :products

  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  root 'store#index', as: 'store'

  # Example of regular route:
  #   get 'products/:id' => 'catalog#view'

  # Example of named route that can be invoked with purchase_url(id: product.id)
  #   get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

  # Example resource route (maps HTTP verbs to controller actions automatically):
  #   resources :products

  # Example resource route with options:
  #   resources :products do
  #     member do
  #       get 'short'
  #       post 'toggle'
  #     end
  #
  #     collection do
  #       get 'sold'
  #     end
  #   end

  # Example resource route with sub-resources:
  #   resources :products do
  #     resources :comments, :sales
  #     resource :seller
  #   end

  # Example resource route with more complex sub-resources:
  #   resources :products do
  #     resources :comments
  #     resources :sales do
  #       get 'recent', on: :collection
  #     end
  #   end

  # Example resource route with concerns:
  #   concern :toggleable do
  #     post 'toggle'
  #   end
  #   resources :posts, concerns: :toggleable
  #   resources :photos, concerns: :toggleable

  # Example resource route within a namespace:
  #   namespace :admin do
  #     # Directs /admin/products/* to Admin::ProductsController
  #     # (app/controllers/admin/products_controller.rb)
  #     resources :products
  #   end
end

The following is the Application Layout:-

<!DOCTYPE html>
<html>
<head>
  <title>Easy Gifts UK Ltd - Home of promotional gifts</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
</head>
<body class='<%= controller.controller_name %>'>
<div id="wrapper">

    <div id="branding">
    <%=link_to( image_tag("easyGiftsLogo.jpg", :width => "210", :height => "70", :alt => "Easy Gifts UK Logo"), store_path) %>
        <div id="search2">
            <p>search field</p>
        </div> 
    </div>

    <div id="content">
        <%= yield %>
    </div>

    <div id="mainNav">
        <ul>
            <li><%= link_to_unless_current('Writing', { action: 'writing' }) %></li>
            <li><%= link_to_unless_current('Office', { action: 'office' }) %></li>
            <li><%= link_to_unless_current('Time', { action: 'time'}) %></li>
            <li><%= link_to_unless_current('Home', { action: 'home'}) %></li>
            <li><%= link_to_unless_current('Wellness', {action: 'wellness'}) %></li>
            <li><%= link_to_unless_current('Travel', {action: 'travel'}) %></li>
            <li><%= link_to_unless_current('Bags', {action: 'bags'}) %></li>
            <li><%= link_to_unless_current('Leisure', {action: 'leisure'}) %></li>          
        </ul> 
    </div>
    <div id="footer">
        <ul>
            <li><%= link_to 'Admin', products_path %></li>
            <li><a href="#">link 2</a></li>
            <li><a href="#">link 3</a></li>
        </ul>
    </div>
</div>
</body>
</html>

And the following is the partial for 'Office':-

<%= image_tag("office (1).jpg", :class => "imgBorder", :width => "808", :height =>"228", :alt => "Office section - Easy Gifts UK Ltd") %>
            <%= render "notice" %>
            <% @products.each do |office| %>
                <div class="item">
                    <%= link_to image_tag(office.image_url), image_path(office.image_url), class: 'fancybox' %>
                    <p><strong><%= office.item_code%></strong>
                    </br><em><%= truncate(office.title, length: 18) %></em></p>                 
                    <p class="showArticle"><%= link_to 'Show Article', store_show_path %></p>
                    <p class="addTo"><a href="#">Quote this item</a></p>
                </div>
            <% end %>
            <p class="clear"><%= will_paginate @products %></p>

And lastly the following is the partial for the 'show' view:-

<h2>Individual Product</h2>

<%= @products.title(:id) %>

Which you can see currently really isn't anything at all as i was just testing getting the info over to it.

The following is the result of rake routes:-

c:\Sites\work\easygifts>rake routes
Prefix          Verb    URI Pattern                     Controller#Action
store_index     GET     /store/index(.:format)          store#index
store_writing   GET     /store/writing(.:format)        store#writing
store_office    GET     /store/office(.:format)         store#office
store_time      GET     /store/time(.:format)           store#time
store_home      GET     /store/home(.:format)           store#home
store_wellness  GET     /store/wellness(.:format)       store#wellness
store_travel    GET     /store/travel(.:format)         store#travel
store_bags      GET     /store/bags(.:format)           store#bags  
store_leisure   GET     /store/leisure(.:format)        store#leisure
store_show      GET     /store/show(.:format)           store#show
products        GET     /products(.:format)             products#index
                POST    /products(.:format)             products#create
new_product     GET     /products/new(.:format)         products#new
edit_product    GET     /products/:id/edit(.:format)    products#edit
product         GET     /products/:id(.:format)         products#show
                PATCH   /products/:id(.:format)         products#update
                PUT     /products/:id(.:format)         products#update
                DELETE  /products/:id(.:format)         products#destroy
store           GET     /                               store#index

Solution

  • There are couple of mistakes in your code:

    a. Lets look at your routes, for your show action your route is:

    store_show      GET     /store/show(.:format)           store#show
    

    For show action you are not passing stores id and so it's nil when you try to find it in your action.

    Fix

    You should use rails resourceful routing. You can do something like this:

    resources :stores do
      collection do
        get "writing"
        get "office"
        get "time"
        get "home"
        get "wellness"
        get "travel"
        get "bags"
        get "leisure"
      end
    end
    

    For your show action this will create a route like this:

    GET /stores/:id(.:format)   stores#show
    

    which will allow you to pass your store id in your link and then you can find it in your controller action

    b. Change your link to this:

    <p class="showArticle"><%= link_to 'Show Article', store_path(office) %></p> // notice we are now passing your product in path helper
    

    c. Show action:

    def show
      @products = Product.find(params[:id]) # notice we have to use params[:id] to find your product also by default find searches your record with id so you don't need to use find_by
      if @products.nil?
        redirect_to action: :index
      end
    end