slave_unit
slave_unit

Reputation: 27

Partial Rendered in index.html.erb Won't Display in show.html.erb

A beginner here, so, please bear with me. :)

I have a partial in a partial that's displaying correctly in my views > products > index.html.erb:

<div>
 <table>
  ...
   <tbody>
    <%= render product %>
   </tbody>
  ...
 </table>
</div>

This is the _product partial:

<div>
 <td>
  <%= render "product_row", product: product, order_item: @order_item %>
 </td>
</div>

..which points to this _product_row partial:

<div>
  <%= form_for order_item, remote: true do |f| %>
   <%= number_to_currency product.price %>
   <%= f.number_field :quantity, value: 1, class: "form-control", min: 1 %>
   <%= f.hidden_field :product_id, value: product.id %>
   <%= f.submit %>
  <% end %>
</div>

All is well, BUT I want to display _product_row in my views > products > show.html.erb instead. So, I copy and paste it and get this error:

NameError in Products#show
undefined local variable or method `product' for #<#<Class:...>
Extracted source:
<%= render "product_row", product: product, order_item: @order_item %>

...so I go in my products_controller and put this:

def show
 @product = Product.find(params[:id])
  respond_to do |format|
   format.html # show.html.erb
   format.json { render json: @product }
  end
end

'still the same error.

Any help will be appreciated.

Thanks!

Upvotes: 0

Views: 802

Answers (3)

slave_unit
slave_unit

Reputation: 27

@Emu and @Dharam suggested that I put

<%= render @product %> instead of <%= render product %>

in my Product show.html.erb and making sure @product is defined in my products_controller.rb, which I did:

def show @product = Product.find(params[:id]) end

It worked! No more undefined errors.

I did have some styling issues with this, though. Long story-short, I copied and pasted what was in my _product_row partial (see original code in the question above) into my Product show instead of rendering it. Then I modified it a bit basing on Emu and Dharam's suggestion. Basically it planted the idea to try to add @s where it errors out as undefined:

<div>
 <%= form_for @order_item, remote: true do |f| %>
  <h4 style="font-family: 'Share Tech Mono', sans-serif;">The Small Price to Pay: 
   <span style="color: green">
    <%= number_to_currency @product.price %>
   </span>
  </h4>
  <h4 style="font-family: 'Share Tech Mono', sans-serif;">How many:</h4>
  <div class="input-group">
   <%= f.number_field :quantity, value: 1, class: "form-control", min: 1 %>
   <div class="input-group-btn, add-to-cart-button">
    <%= f.hidden_field :product_id, value: @product.id %>
    <%= f.submit "ADD IT", class: "btn btn-danger" %>
   </div>
  </div>
 <% end %>
</div>

Then added this to my products_controller.rb:

def show @product = Product.find(params[:id]) @order_item = current_order.order_items.new end

I hope this makes sense. Thanks, again, all. :)

Upvotes: 0

Dharam Gollapudi
Dharam Gollapudi

Reputation: 6438

I am guessing you probably have some loop as follows in your index.html.erb

<% @posts.each do |post| %>
  <%= render product %>
<% end %>

Here product in the render call refers to the local variable you defined in the block of the iterator.

But when you try to copy/paste the same code to your show.html.erb, product will is considered undefined as it is out of the loop.

So you should use the following:

<%= render @product %>

in your show.html.erb, assuming you must have assigned @product in your show action.

Upvotes: 1

Emu
Emu

Reputation: 5895

You are rendering your partial from index.html.erb file like:

<%= render product %>

here, product variable is not defined as a local variable in the view file. From your controller's index action pass product variable as a instance variable like @product or define it in the index.html page.

Or, you can do simply like that: in products_controller > index

def index 
  @products = Product.all
end

in products > index.html.erb

<% @products.each do |product| %>
<div>
 <table>
  ...
   <tbody>
    <%= render product %>
   </tbody>
  ...
 </table>
</div>
<% end %>

Upvotes: 1

Related Questions