error while rendering a partial in rails3 - ruby-on-rails

I am trying to render a partial in rails using the normal
<%=render 'subtasks/descform %> command
Now the issue is that this descform partial is being called from inside another partial which is 'subtasks/subtask' and their are many subtasks.
So the subtask partial is also getting rendered from the task partial like this
<% task.subtasks.each do |subtask| %>
<%=render :partial=>subtask %>
<%end%>
So the problem is in the desc form,it has a form like this
<%=form_for subtask,:remote=>:true,:method => :put do |f| %>
<%= f.text_area :description,rows:'5',cols:'12',:class=>'myarea'%>
<%= f.submit "save",class:'btn btn-success col-md-4' %>
<a data-id='<%=subtask.id %>' href="#" class="myclose"><i class="fa fa-times fa-lg" style="margin:10px auto;"></i></a>
<% end %>
So,when i am trying to render this form i am getting an error
undefined local variable or method `subtask' for #<#:0x458f6b8>
Can somebody please explain the cause of this error and how to fix this.

You just need to pass the variable to the partial, like so:
<%=render 'subtasks/descform', :subtask => subtask %>
Then it will be accessible in your partial as subtask

Pass the subtask object as a local variable to descform partial. First to subtask partial and then to descform
<% task.subtasks.each do |subtask| %>
<%=render :partial => 'subtask', :locals => {:subtask => subtask} %>
<%end%>
And inside subtask partial, pass it on to descform
<%=render :partial => 'subtasks/descform', :locals => {:subtask => subtask} %>
You have to mention partial when you pass in locals. For eg, the following will not work
<%=render 'subtasks/descform', :locals => {:subtask => subtask} %>

In the task partial:
<%= render :partial => "subtask", :collection => task.subtasks %>
In the subtask partial:
<%=render :partial => 'subtasks/descform', :locals => {:subtask => subtask} %>

Related

Using ajax to render partial

In my rails app I have a model Song. On one of the user's profile pages user_music_path(#user) I'm rendering all of their songs.
People can also like these songs, which is set up and working, I just want to use AJAX instead of page refreshes. The problem I'm having is when using ajax, I get the error undefined local variable or method "song" when I'm clicking the link "like".
Here is some of my code:
User's Music Page views/users/music.html.erb
...
<ul class="playlist list-group">
<%= render #songs %>
</ul>
views/songs/_song.html.erb
<li class="list-group-item">
<p class="pull-right">
<%= render :partial => 'songs/like_button', :locals => {:song => song} %>
<%= render :partial => 'songs/likes', :locals => {:song => song} %>
</p>
</li>
views/songs/_like_button.html.erb
<% if current_user.voted_on?(song) %>
<%= link_to "Unlike", unlike_song_path(song), :method => :post, :remote => true %>
<% else %>
<%= link_to "Like", like_song_path(song), :method => :post, :remote => true %>
<% end %>
views/songs/_likes.html.erb
<%= song.votes.count %>
views/songs/like.js.coffee
$("p.pull-right").html('<%= render :partial => "songs/like_button", :locals => {:song => song} %><%= render :partial => "songs/likes", :locals => {:song => song} %>');
controllers/songs_controller.rb
def like
begin
#vote = current_user.vote_for(#song = Song.find(params[:id]))
#vote.save
respond_with #song.user, :location => user_music_path(#song.user)
rescue ActiveRecord::RecordInvalid
redirect_to #song
end
end
And as mentioned earlier, the :like action worked perfectly before I starting using AJAX. I've also added respond_to :html, :js to my songs_controller. And the error I get when I try to like the song is ActionView::Template::Error (undefined local variable or method "song" for #<#<Class:0x000001028de9d0>:0x00000106ecd9f0>):
Where you have
<%= song.name %>
try instead
<%= #song.name %>
And do the same with your link_to paths and your render calls.
Do rake routes and use of of them for the link, e.g. (pseudo-code) link_to 'song', song_audio_path

How can I display a list of child records?

I have a table of accounts and venues where an account can have many venues.
I'm displaying all the accounts as partials on the accounts index page and would like for each one to include the names of the venues linked to them.
Heres what I have:
account partial
<%= link_to free_account do %>
<div class="account_partial">
<span class="account_header"><%= free_account.name %></span> - <span class="free_account_highlight">(<%= free_account.role %>)</span><br>
<%= render :partial => 'venues/account_venue', :collection => #account.venues %>
</div>
<% end %>
account_venue partial
<%= venue.name %>
I'm getting this error:
NoMethodError in Accounts#index
undefined method `venues' for nil:NilClass
Extracted source (around line #12):
12: <%= render :partial => 'venues/account_venue',
:collection => #account.venues %>
Any help would be much appreciated!
edit
accounts_controller
class AccountsController < ApplicationController
load_and_authorize_resource
def index
#accounts = Account.all(:include => :venues)
end
end
accounts index.html.erb
<div id="narrow_container">
<div class="free_accounts_container">
<h2 class="show_orange">Free accounts</h3>
<%= render :partial => 'free_account', :collection => #accounts %>
</div>
<div class="premium_accounts_container">
<h2 class="show_orange">Premium accounts</h3>
<%= render :partial => 'premium_account', :collection => #accounts %><br><br>
</div>
<div class="clearall"></div>
<div class="button">
<%= link_to 'add account', new_account_path %>
</div>
</div>
_free_account.html.erb
<%= link_to free_account do %>
<% if free_account.role == "free" %>
<div class="account_partial">
<span class="account_header"><%= free_account.name %></span> - <span class="free_account_highlight">(<%= free_account.role %>)</span><br>
<div class="owner_details">
<span class="pre_account_highlight">Owners username:</span><span class="account_highlight"><%= free_account.user.username %></span>
<span class="pre_account_highlight">Owners e-mail:</span><span class="account_highlight"><%= free_account.user.email %></span>
</div>
<div class="account_details">
</div>
<%= render :partial => 'venues/account_venue', :collection => #account.venues %>
</div>
<% else %>
<% end %>
<% end %>
update
If I change the partial call to:
<%= render :partial => 'venues/account_venue', :collection => #accounts %>
and the account_venue partial to just read 'test' it loads without error but displays the word test 4 times (theres 4 account records) if I add a new account record it displays the word test 5 times.
You need to set #account to something in your controller, and that model instance should be joined to (or include) the Venues model. Like so:
#account = Account.find(params[:id], :include => :venues)
Edit: I take it you have already set up your Account and Venue models with has_many and belongs_to relationships?
Edit two: I see now that you're trying to access Accounts#index, in which case the code above should be changed to something like (since we're not looking at one specific account):
#accounts = Account.all(:include => :venues)
Edit three: Now that you've posted the controller and partials code as well, a couple of things stand out; When rendering a partial using a collection the resulting object inside the partial derives its name from the partial and not the collection. From the Rails Guides:
"When a partial is called with a pluralized collection, then the
individual instances of the partial have access to the member of the
collection being rendered via a variable named after the partial."
In your partial _account_venue.html.erb you have <%= venue.name %> - this needs to be changed to <%= account_venue.name %>.
Secondly, in _free_account.html.erb, where you call the account_venue partial, you're referring to a collection object named #account - where does this come from? Since the free_account partial is also called with a collection, the object you should be using will be called free_account - indeed you are referencing it by this name earlier in the same partial when you do <%= free_account.name %>. So the render partial call should look like this:
<%= render :partial => 'venues/account_venue', :collection => free_account.venues %>
Hope this helps!
Looks like your not assigning #account to anything. Should this be free_account instead?

How to change to view helper method?

I am working on a app where you can add task etc. I know this is kind of weird but I just like to see how others would implement this. How would you change the following code into a helper method and use it?
The original code
<h2>My Tasks</h2>
<% task = #work.tasks %>
<% if task.empty? %>
<%= link_to 'Create a new task', new_task_path %>
<% else %>
<%= render :partial => 'notes/note', :locals => {:note => #note} %>
<% end %>
My way of doing a helper method
def task_check
task = #work.tasks
if task.empty?
link_to 'Create a new task', new_task_path
else
render :partial => 'notes/note', :locals => {:note => #note}
end
end
In my view
<%= #work.task_check %>
Personally, I wouldn't extract this out at all, this is view logic and it belongs in the views. It definitely doesn't belong in a model, but it could arguably be extracted into a helper. I'd change it slightly:
<h2>My Tasks</h2>
<% if #work.tasks.blank? %>
<%= link_to 'Create a new task', new_task_path %>
<% else %>
<%= render :partial => 'notes/note', :locals => {:note => #note} %>
<% end %>
Calling blank? instead of empty? will work even if #work.tasks is nil
.
You can't define a helper in the model. It won't have access to render, link_to or any other controller or view methods. So just define your method almost exactly as is in a file in your helpers directory, maybe application_helpers.rb or work_helpers.rb:
def task_check(work, note)
task = work.tasks
if task.empty?
link_to 'Create a new task', new_task_path
else
render :partial => 'notes/note', :locals => {:note => note}
end
end
And then call it in your view like so:
<%= task_check(work, note) %>

An instance of a model to render into a partial

I render an instance of a model into a partial with the following code <%= render #places %>.
I created _places.html.erb. I thought I could use the following code since the render method is supposed to iterates trhough the places collection :
<li>
<%= link_to place.name, place %>
</li>
I get this error : undefined local variable or method 'place' for #<#<Class:0x007fc1c0a4e6b8>:0x007fc1c05050a8>
I have to use to make it work :
<% #places.each do |place| %>
<li>
<%= link_to place.name, place %>
</li>
<% end%>
try this:
<%= render :partial => 'places.html', :collection => #places, :as => :place %>
Or, if you have the partial file as singular name, you can do it like this(without the variable :as)
<%= render :partial => 'place.html', :collection => #places %>

Rendering Partial onclick in Rails

I am trying to render a partial onclick to save on page loading time.
<ul id="pop_twitter">
<% #topic_count.each do |k,v| %>
<% #k = k %>
<!-- make a link that onclick renders a partial below -->
<li><% link_to_remote k, ?????? %></li>
<ul id="twitter_<%= k %>" style="display:none;">
<!-- where the partial should load -->
</ul>
<% end %>
</ul>
I need to load the partial 't_tweets' and it also need the variable 'k' in from the .each loop.
here's a rough start:
link_to_remote("Show", :url => {:action => 'show_tweets', :k => k})
EDIT: i guess since you're only showing a partial, it would make sense to also pass :method => :get, since link_to_remote defaults to :post.
and in your controller
def show_tweets
render :update do |page|
page.insert_html :bottom, 'pop_twitter', :partial => 't_tweets', :locals => params[:k]
page["tweet_#{params[:k]}"].visual_effect :highlight #using scriptaculous
end
and your partial
<div id="<%= "tweet_#{k}" %>">
<%= tweet.body %>
</div>

Resources