Yuri Gravatá
Yuri Gravatá

Reputation: 23

Rails - Problem with passing local variables

I'm running Rails 6.0.3.2 and I want to render a partial passing a local variable to another controller view:

My routes:

Rails.application.routes.draw do
  devise_for :users

  root to: 'notebooks#index'

  resources :notebooks, only: [:index, :new, :show, :create, :edit, :update, :destroy] do 
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
    collection do
      get "list"
    end
  end

  resources :tags

end

Notebook Model:

class Notebook < ApplicationRecord

  has_one_attached :photo
  validates :asin, presence: true, uniqueness: true
  after_initialize :init
  
  acts_as_list column: :position, add_new_at: :bottom

  has_many :taggings
  has_many :tags, through: :taggings

  def init
    self.edited ||= false
  end

end

Tag Model

class Tag < ApplicationRecord
  has_many :taggings
  has_many :notebooks, through: :taggings
end

In Tag controller:

  def index
    @tags = Tag.all.order(created_at: :asc)
  end

I tried to follow this guide and render the "index view" from Tags Controller on the "list view". The application finds the tags/_index.html file, but return the error undefined method `each' for nil:NilClass. Bellow my views code:

In app/views/notebooks/list.html.erb:

  <%= render :partial => "tags/index" , locals: {tags: @tags}%>

In app/views/tags/_index.html.erb

<% tags.each do |tag| %>
  <div>
    <div class="d-flex">
      <p><%= tag.id %></p>
      <p><%= tag.name %></p>
    </div>
    <p>tag.taggings.count</p>
  </div>
<% end %>

Anyone can point me what i'm doing wrong? I read the Layouts and Rendering in Rails documentation, but i don't have a clue why the instructions won't work on my project...

Thanks in advance!

Upvotes: 2

Views: 252

Answers (2)

stevec
stevec

Reputation: 52268

I had the same problem where a local wasn't showing up in the partial. Here's my code:

<%= render "chats/messages", locals: { chat: @chat } %>

but it needed to be:

<%= render partial: "chats/messages", locals: { chat: @chat } %>

Then it worked as expected (the chat local variable was available in the partial).

Upvotes: 0

max
max

Reputation: 102036

The rails way to do this is just to create a partial for a single record:

# app/views/tags/_tag.html.erb
<div>
  <div class="d-flex">
    <p><%= tag.id %></p>
    <p><%= tag.name %></p>
  </div>
  <p>tag.taggings.count</p>
</div>

You can then pass the collection to render and Rails will look up the partial and render it for each member in the collection:

<%= render @tags %>

This is short for:

<%= render partial: 'tag', collection: @tags %>

See Rendering Collections.

Upvotes: 2

Related Questions