How to render a specific Product page based on drop down selections

I’m trying to build some functionality that displays the correct heart worm medication for a specific breed of dog and their living environment.

First the user selects the breed (lab, bloodhound, toy poodle, etc.) from a list of breeds on the page. The user is then redirected to a detail page about that breed, listing some characteristics. On this page there will be two drop downs: one listing the type of food they are eating: hard food, wet canned, or raw diet; then a second drop down listing the dog’s living environment (indoor or outdoor).

Based on these two selections I would like to redirect the user to a Product page based on the above choices: breed, food, living environment.

I’ve already written out all the possible combinations, for example, poodle → raw/indoor → Product C

I guess my primary question is how do I capture what the user has selected in the two drop down boxes and render a product page based on that?

I figure my models are: Dog and Product

Thanks so much!

EDIT

I should add that I just need some big picture nudging. I know this is a very broad question.

I think you’re missing a model.

I would have a medication_reccomendation model that takes breed, food, and living environment and spits out a product ID.

The breed page controller show action would initialize a new medication_recomendation model with the breed set. The view would create a form for that with the breed as a hidden input, and the two select boxes you need. The form would post to the medication_reccomendations controller (create action).

The create action on that controller would instantiate the medication_recomendation model with the inputs and then redirect_to the product page for the returned product.

You’ll be getting the values from the dropdowns in the params hash.

Since you’d like to render several pages, you’ll probably want to copy them to the session hash, which persists between requests.

Then, after the final dropdown is selected, you’ll want to pull the values and send them to a method that will answer with which product (or perhaps partial) to render.

Derek’s answer is better, and is what I would do, personally. The approach I recommended to you was chosen for simplicity, since it seems like you’re probably a beginner.

So, if his answer makes sense–do that!

Thanks very much. Once the medication_recommendation object is instantiated how would I tie that back into the correct product_id?

It’s definetely going to be a little bit tricky. I’d probably have something like this (Not sure this is correct, but it’s in the right direction). It assumes Rails 4 (by using the find_by method) and isn’t without it’s problems. There’s probably even more objects to extract here, but this is a start that’s complicated enough as is!

class MedicationRecommendation < ActiveRecord::Base
  # The table structure here looks like:
  # * id
  # * breed_id
  # * environment
  # * diet
  # * product_id
  #
  # You'd have to seed it with all of the various permutations.
  belongs_to :breed
  belongs_to :product
end

class MedicationRecomendationsController < ApplicationController
  def create
    recomendation = MedicationRecomendation.find_by({
      breed_id: params[:breed_id],
      environment: params[:environment],
      diet: params[:diet]
    })

    redirect_to recomendation.product
  end
end

Make sense?

1 Like

Would you mind showing me what a demo form for the show page would look like? Thank you!

Right now I have the following:

<%= form_for @product_recommendation do |form| %> <%= form.hidden_field :ant_id %> <%= form.select :environment, options_for_select([["Select One"], "Indoor", "Outdoor"]) %> <%= form.select :diet, options_for_select([["Select One"], "Sugar", "Fat", "Protein"]) %> <%= form.submit "Submit" %> <% end %>

How do I send this to the product_recommendations table while also matching the up the attributes and spitting out the missing attribute. My ProductRecommendation model looks like this:

=> ProductRecommendation(id: integer, ant_id: integer environment:string, diet:string, created_at: datetime, updated_at: datetime,)

That’s what the controller is for. In the controller action that form posts to, you need to do something like:

recomendation = ProductRecomendation.find_by({
      ant_id: params[:ant_id],
      environment: params[:environment],
      diet: params[:diet]
    })

redirect_to recomendation.product

That is, you pull all the parameters you need for the query from the params hash.

Right, I understand that part, but how do isolate the recommendation id that matches all of these? Also, this seems like it is more of a query, should I be creating a record in the db via the create action in the controller or simply searching through all of the possible permutations?

Maybe I’m confused by what exactly find_by is doing. Can you explain what all is happening here:

recommendation = ProductRecomendation.find_by({
    ant_id: params[:ant_id],
    environment: params[:environment],
    diet: params[:diet]
})

redirect_to recomendation.product

What is find_by doing? I’m not having any luck finding good documentation on it. And where is ‘product’ in

recommendation.product

coming from?

I appreciate your help.

Here is the documentation for find_by.

It’s performing a database query on the product_recommendations table looking for rows where the passed in conditions match. As I said earlier, the solution relies on you populating that table with a mapping of all ant_id, environment, diet, and product_id combinations. Once that’s done, the query above will return the row that matches for ant_id, environment, and diet and then you call product on that to get the product that row points to.

Have you taken the intro rails course available to you as a prime subscriber (at workshops level or higher)? This type of thing should be covered there and will probably be a big help.

Thanks, that makes sense. But why am I creating a record if all we’re doing is querying a table?

You’re using the create action on the controller but you’re not actually creating a record. I don’t love this about the idea (it was one of the things I was eluding to when I said the approach wasn’t without its problems). You don’t have to persist a record to the database when using the create action.

You can have the form use a different action but you’ll need to change the action on the form_for call and possibly change the routes.