Skip to content

Instantly share code, notes, and snippets.

@jennceng
Last active January 11, 2017 14:41
Show Gist options
  • Save jennceng/1d92494094979cde4b490cd99a642e6a to your computer and use it in GitHub Desktop.
Save jennceng/1d92494094979cde4b490cd99a642e6a to your computer and use it in GitHub Desktop.
class ReviewsController < ApplicationController
  def index
    # use the product id from params to find the product of interest, the key of the params hash can always be seen in the dynamic portion of the URI via rake routes
    @product = Product.find(params[:product_id])
    @reviews = @product.reviews
  end

  def new
    @product = Product.find(params[:product_id])
    @review = Review.new
  end

  def create
    @product = Product.find(params[:product_id])
    @review = Review.new(review_params)
    # assign the relationship between the review and product
    @review.product = @product

    if @review.save
      flash[:notice] = "Review saved successfully."
      redirect_to product_path(@product)
    else
      flash[:alert] = "Failed to save review."
      render :new
    end
  end

  def review_params
    params.require(:review).permit(:body)
  end
end
# alternative syntax for saving the correct product to the review:
class ReviewsController < ApplicationController
  def index
    @product = Product.find(params[:product_id])
    @reviews = @product.reviews
  end

  def new
    @product = Product.find(params[:product_id])
    @review = Review.new
  end

  def create
    @review = Review.new(review_params)

    if @review.save
      flash[:notice] = "Review saved successfully."
      redirect_to product_path(@product)
    else
      flash[:alert] = "Failed to save review."
      render :new
    end
  end

  def review_params
    params.require(:review).permit(:body).merge(product: Product.find(params[:product_id]))
  end
end

Forms: If a form has its own page, the form_for will have to have an array that hold both the object for the parent and the child, where the parent was defined as an instance variable in the Review#new

class ReviewsController < ApplicationController
  ...
  def new
    @product = Product.find(params[:product_id])
    @review = Review.new
  end
  ...
end
<h1>New Review for <%= @product.name %></h1>

<%= form_for [@product, @review] do |f| %>
  <%= f.label :body %>
  <%= f.text_field :body %>

  <%= f.submit %>
<% end %>

Simply consider whether or not it will be necessary, for example if the form for a new review was on the product show page, you would not need a nested route (unique URL) for the form, and would instead have:

class ProductsController < ApplicationController
  ...
  def show
    @product = Product.find(params[:id])
    @review = Review.new
  end
  ...
end
# products/show.html.erb
<h1>New Review for <%= @product.name %></h1>

<%= form_for [@product, @review] do |f| %>
  <%= f.label :body %>
  <%= f.text_field :body %>

  <%= f.submit %>
<% end %>
# submission will hit Review#create
class ReviewsController < ApplicationController
  def create
    @review = Review.new(review_params)
    if @review.save
      flash[:success] = "Review has been successfully created!"
    else
      flash[:error] = @review.errors.full_messages.join(", ")
    end
    redirect_to post_path(@review.post)
  end
  ...
  private
  def review_params
    params.require(:review).permit(:body).merge(product: Product.find(params[:product_id]))
  end
end 

Path helpers: keep in mind that with nested routes, for exmaple if you are trying to go to a review show page or rerender a form template if you filled it out incorrectly, you must make sure to define and pass in both the parent and child objects

  • rake routes is your best friend
  • use | grep thingofinterest to filter through routes
# example of how to use path helper, pass in the arguments in the correct order of nesting, use URI in rake routes to help inform you
product_review_path(@product, @review)

don’t forget about dependents: destroy, if you don’t, if you try to go to the review index page for example, it might blow up since the product has been deleted, but its reviews haven’t

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment