Rendering partial with locals in Haml? - ruby-on-rails

I am learning Haml.
My view files are like:
show.html.haml:
.content
= render 'meeting_info', :locals => { :info => #info }
and _meeting_info.html.haml:
.detail
%table
%caption
Meeting Informations of
= info["meeting_name"]
...
When I tried running this I got an undefined local variable or method 'info' error.

Try this
Without :locals and :partial
.content
= render 'meeting_info', :info => #info
No need to specify locals.
With :locals and :partial
You should specify locals in following case i.e specifying :partial for render
.content
= render :partial => 'meeting_info', :locals => { :info => #info }

You would use the :locals option if you're calling render from a controller. When calling render from a view, you would simply do this:
= render 'meeting_info', :info => #info

Related

How to render two paginated and ajaxable collections in the same view?

In a Rails 3.2 index view I am rendering two partials.
<%= render :partial => 'users/user', :locals => {:users => #happy_users} %>
<%= render :partial => 'users/user', :locals => {:users => #sad_users} %>
and in the partial
<% users.each do |user| %>
Show some fields
<% end %>
<%= will_paginate users %>
The pagination is not working.
If I alter will_paginate to take an instance variable, pagination works (but the wrong collection)
<%= will_paginate #users %>
How can I pass locals to will_paginate when the partial is called?
(I realize that I'll also need to pass :param_name to get this working with two collections. For now I'm just trying to get one instance working.)
The partial is rendered via index.js.erb
$(".ajaxable-users").html('<%= escape_javascript(render("users/user")) %>');
And the controller looks like
def index
#users = User.scoped.paginate(:page => params[:page], :per_page => 5)
#happy_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5)
#sad_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
format.json { render :json => #users }
format.js
end
end
Thanks for any ideas.
you need to make sure the controller knows which page link of which listing you press. we do this by passing a param to will_paginate page link generator.
you need to make sure your js updates the correct html tag when refreshing the pagination of either listing. we do this by wrapping the pagination in a mood-dependent :) div tag.
since we share the partial we need to make sure mood as well as correct collection is set in controller and passed to partial as local from index views (both html and js).
finally make sure your ajax remote picks up after you redraw pagination (this is a bonus)
so, to set controller instance vars depending on request mood parameter
note that this code also spares you some db calls, since if you just pagintae sad users you do not need to retrieve happy ones or all).
I ommit #users for simplicity, its never used
I suspect happy scope for sad users is only a typo
.
# controller
def index
#mood = params[:mood]
#mood_users = #happy_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5) if #mood.blank? || #mood == 'happy'
#mood_users = #sad_users = User.happy_scope.paginate(:page => params[:page], :per_page => 5) if #mood.blank? || #mood == 'sad'
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
format.json { render :json => #users }
format.js
end
end
make sure we dispatch the right locals to partials:
# index.html.erb
<%= render :partial => 'users/user', :locals => {:users => #happy_users, :mood => 'happy' } %>
<%= render :partial => 'users/user', :locals => {:users => #sad_users, :mood => 'sad' } %>
make partial mood sensitive allowing for distinct div tag id. also put mood in request url.
# users/user partial
<div id='<%= "#{mood || ''}users"%>'>
<% users.each do |user| %>
Show some fields
<% end %>
<%= will_paginate users, :params => { :mood => mood } %>
</div>
this js allows for refreshing different collections in different divs depending on which pagination link was pressed.
# index.js.erb
$("#<%= #mood %>users").html('
<%= escape_javascript(render(partial: "users/user", locals: { users: #mood_users, mood: #mood })) %>
');
For unobtrusive ajax links for pagination you need.
Ruby - Rails 3 - AJAXinate Paginate and sorting
# in a generic js
$(document).ready(function () {
$(".pagination").find("a").livequery(function () {
$(this).attr("data-remote", true);
});
});
Note that the solution should even work if javascript is not enabled and we fall back on html. In this case both sections should be redisplayed allowing for different pages.
MODIFIED CODE TO ALSO HANDLE GRACEFUL JS FALLBACK TO HTML
controller
# controller
def index
#mood = params[:mood]
#happy_page = #mood == 'happy' ? params[:page] : params[:happy_page]
#sad_page = #mood == 'sad' ? params[:page] : params[:sad_page]
#mood_users = #happy_users = User.happy_scope.paginate(:page => #happy_page, :per_page => 5) if !request.xhr? || #mood == 'happy'
#mood_users = #sad_users = User.happy_scope.paginate(:page => #sad_page, :per_page => 5) if !request.xhr? || #mood == 'sad'
#mood_users = #users = User.scoped.paginate(:page => params[:page], :per_page => 5) if #mood.blank?
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
format.json { render :json => #users }
format.js
end
end
forward new view vars to partial local
# index.html.erb
<%= render :partial => 'users/user', :locals => {:users => #happy_users, :mood => 'happy', :happy_page => #happy_page, :sad_page => #sad_page } %>
<%= render :partial => 'users/user', :locals => {:users => #sad_users, :mood => 'sad', :happy_page => #happy_page, :sad_page => #sad_page } %>
we only need to pass this here to not get undefined method in partial.
# index.js.erb (fixed HTML syntax)
$("#<%= #mood %>users").html('
<%= escape_javascript(render(partial: "users/user", locals: { users: #mood_users, mood: #mood, :happy_page => #happy_page, :sad_page => #sad_page })) %>
');
this will then persist happy pages in param if sad page link is clicked, and vica versa.
# users/user partial
<div id='<%= "#{mood || ''}users"%>'>
<% users.each do |user| %>
Show some fields
<% end %>
<%= will_paginate users, :params => { :mood => mood, :happy_page => happy_page, :sad_page => sad_page %>
</div>
First, create in controller two diferent methods for each list for example fill_list1 and fill_list2 there are independent of method for create the main page for example index
Each list method must render a partial without layout for example
render :partial=>'fill_list1', :layout => false
The main page must call partials in view for first time.
when you click in paginate control you must hack click for call ajax next pagination items list
$('list1 a').live('click', function(event){
event.preventDefault();
$.ajax(
{url:URLFORCALLMETHODLIST,
success: function(content) {
DIVLOCATIONLIST.html(content);
},
async:false,
});
});
Try passing proper locals in the index.html.erb:
$(".ajaxable-users").html('
<%= escape_javascript(render("users/user", locals: { users: #users })) %>
');

How to have a multi-line return for a function in Rails / Ruby?

The following only renders the last partial line:
def default_sidebars
render :partial => 'shared/sidebars/box1'
render :partial => 'shared/sidebars/box2'
render :partial => 'shared/sidebars/box3'
render :partial => 'shared/sidebars/box4'
end
How could I get it to render all lines?
def default_sidebars
res = render :partial => 'shared/sidebars/box1'
res += render :partial => 'shared/sidebars/box2'
res += render :partial => 'shared/sidebars/box3'
res += render :partial => 'shared/sidebars/box4'
end

Rails how can I pass collection to a partial view, that is rendered from *.js.erb file

When I do this in my update.js.erb from the RewardsController:
$('div#rewards_list').html("<%=
escape_javascript(render :partial => 'shared/rewards',
:collection => #rewards,
:as => reward,
:locals => { :user => #user }
)
%>");
But the log says:
ActionView::Template::Error (undefined local variable or method `reward' for
#<#<Class:0xbb395d8>:0xbb3774c>):
In my 'update' action method:
def update
#user = User.find(params[:user_id])
#reward = #user.rewards.find(params[:id])
respond_to do |format|
if #reward.update_attributes(params[:reward])
#rewards = #user.rewards
format.html { redirect_to #user }
format.js
else
flash[:error] = "There is an error while updating the reward, please try again!"
format.html { redirect_to #user }
end
end
end
The :as option should be given a symbol, not a variable (and especially not a variable that doesn't exist), perhaps you mean this:
$('div#rewards_list').html("<%= escape_javascript(render :partial => 'shared/rewards', :collection => #rewards, :as => :reward, :locals => {:user => #user}) %>");
I just changed :as => reward to :as => :reward. See the Layouts and Rendering in Rails guide for details.

Ajax and vote_fu | missing before statement

relate question: Vote_fu and Ajax requests
There seems to be something wrong with my Ajax request.
What I 'm trying to do is on event click vote submit a vote then update page with out refreshing the page.
votes_controller.rb:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
link | for view album show :
<%= link_to_remote "Vote Up",
:url => user_album_votes_path(album.user, album,
:vote => :true, :format => :js),
:method => :post %>
application.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
jQuery(document).ready(function() {
$("#votes_.album").bind('click');
})
create.js
page.replace_html "#votes_{#album.id}",
:partial => "album_vote",
:locals => {:album => #album}
This is the following error message which I'm getting:
missing ; before statement
[Break on this error] page.replace_html "#votes_#{#album.id}", ...bum_vote", :locals => {:album => #album}
I'm not sure what is going wrong here I have been following many example from the vote_fu doc's
still having problems.
http://github.com/peteonrails/vote_fu/tree#readme
one amendment made on create.js
there is now another error:
No the error has moved over to the votes_controller
NoMethodError (You have a nil object when you didn't expect it!
<br />
The error occurred while evaluating nil.vote):
app/controllers/votes_controller.rb:53:in `create'
app/controllers/votes_controller.rb:52:in `create'
<br />
Rendered rescues/_trace (128.4ms)
Rendered rescues/_request_and_response (0.4ms)
Rendering rescues/layout (internal_server_error)
These lines are on the create action, which looks perfectly fine!?
How do I get this to work?
Regard
Dan
Try changing the create.js to
page.replace_html "#votes_#{#album.id}", :partial => "album_vote", :locals => {:album => #album}
You might have missed the # for the variable string interpolation.
Solved!
The problem was that I didn't add a before statement to refresh the vote count!
so I did and it worked as well as that, I changing the create.js to create.sj.erb, also I made some small changes to my application.js file. After all that I then added a flash[:note] = you have voted!, then added a function to remove the flash notice after a sec and fadeOut!
For anyone who's interested heres the code:
Application.js
jQuery(document).ready(function() {
$("#vote").bind('click', function(e) {
if (e.target.tagName == "DIV") {
$(this).find(".album_extened").toggle('blind');
}
})
})
create.js.erb
$("#vote").before('<div id="notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#vote_count").html("<%= #album.votes_for - #album.votes_against %>");
$(document).ready(function() {
setTimeout(hideFlashMessages, 1000);
});
function hideFlashMessages() {
$("#vote, #notice").append('').fadeOut(1000);
}
If anyone knows a better why which this can be done please forward!!
A good viewing of [http://railscasts.com/episodes/136-jquery][1]
Reading of [link text][2]
Soon fixed things Thanks Jonathanlink text
[1]: http://railscasts.com/episodes/136-jquery/"Rails Cast ep 136"
[2]: http://www.notgeeklycorrect.com/english/2009/05/18/beginners-guide-to-jquery-ruby-on-rails/"Beginners Guild to jQuery and Rails"
and Thanks Sam for being helpful!!
It seems to me that the current_user in the create method did not get its value set.
How do you set the current_user value? In other plugins, they usually define this as an
instance method or instance variable with accessor.
So maybe changing the create method to the following might help:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if #current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
You might have missed the # before the current_user.vote

render_to_string stripping markup

I am using render_to_string within a JSON 'render' response. The render_to_string method seems to be striping my HTML, what am I doing wrong here?
Here's a sample:
render :json => {:html => render_to_string(:partial => 'view', :locals => { data => #data} )}
The response is coming through without any markup on it.
Have you tried setting the template format in the respond_to block like this:
format.json do
#template.template_format = :html
#html = render_to_string( :partial => 'view', :locals => { data => #data} )
render :json => { :success => true, :html => #html }
end

Resources