Simple ajax rails 3 call troubles - ruby-on-rails

So i'm trying to make a simple ajax call in rails 3 but can't get the ajax to return properly. I think I'm missing something obvious but I've been trying for the past 3 hours so I figured it's time to ask.
I'm attempting the ajax call on the index page of the post model which is supposed to return search results.
My posts_controller.rb for the index action looks like this.
def index
#posts = Post.search(params[:search])
respond_to do |format|
format.html # index.html.erb
format.js #ajax call
format.json { render json: #posts }
end
end
My index.html.erb (which contains the search text field and div where (ajax) results are to be returned looks like this
<%= form_tag posts_path, :method => "get", :remote => true do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :class => "btn", :name => nil %>
<% end %>
<div id="posts">
<%= render #posts %>
</div>
My _post.html.erb looks like this
<table>
<tr>
<td class="well well-small"><%= post.title %></td>
<td class="well"><%= post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<br />
<br />
</table>
My index.js.erb looks like this
$("#posts").html("<%= escape_javscript(render :partial => "new" ) %>");
and my post.rb model page looks like this
class Post < ActiveRecord::Base
attr_accessible :content, :title
def self.search (search)
if search
find(:all, :conditions => ['title LIKE ?', "%#{search}%"])
else
find(:all)
end
end
end
Sorry there has to be so much code just wanted to show everything relevant. For some reason my search results aren't being updated with ajax. When I remove the :remote => true from the form in index.html.erb and remove the index.js.erb file, the search results are returned fine(without ajax) so my search functionality is not the problem.
Thanks in advance for your help. As always if you give me a good answer, I will accept it as the right one.

The problem is that you're not re-rendering your new collection of posts, you're rendering the 'new' partial!
Try this instead on your index.js.erb file:
$("#posts").html("<%= j(render :collection => #posts ) %>");
Do not change anything else from what you posted and it should work.

If I understand your problem, after your ajax request you want update your view: so I would try something like this in your posts_controller.rb:
format.js do
render :update do |page|
page.replace_html 'id_of_your_refreshed_element', :partial => 'partial_content_refreshed'
end
end
It should work. Your partial_view will take in consideration your new #posts variable.
I hope It will help you.

Related

DRYing code resulted in doubling output

I am making a resume application to list my employment history, education history and other responsibilities. This is my first rails application on my own without a tutorial, but much of what I do is just following the same actions. All the code is here: https://github.com/victorman/portfolio
Quick summary. I ajaxed my app a bit, and got it to work. But I had a template with the exact same html as part of a view, so I replaced that portion with a render :partial.... The result was twice the html as before. Below is a more detailed description of what I did to the app.
I made two scaffolds, one for Jobs and one for Categories. Jobs has a foreign key to categories.
I made the Jobs view list a link for each category. The jobs#index controller then only finds the rows in the jobs table for that category.
Then I decided to throw some ajax in there so that clicking a link would only reload the relevant data. I added a respond_to at the end of the jobs#index method.
def index
#find which jobs to display based on category_id in the url params
#if no category_id param is given default to 1
unless params.has_key? :category_id
#jobs = Job.find(:all, :conditions => {:category_id => 1})
else
#jobs = Job.find(:all, :conditions => {:category_id => params[:category_id]})
end
respond_to do |format|
format.html
format.js #index.js.erb
end
end
I made a index.js.erb file that retrieves the new data and replaces the old.
var jobs = $("<%= escape_javascript(render(:partial => #jobs))%>").hide();
$("#jobs_table").replaceWith(jobs);
$("#jobs_table").fadeIn();
I added remote: true to the links in the jobs index.html.erb file.
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, { :controller => "jobs", :category_id => "#{category.id}" }, :class => "category_link", remote: true %></li>
<% end %>
</ul>
And I made the template partial where the jobs were displayed. it would never find _jobs.html.erb so i had to name it _job.html.erb
<tbody id="jobs_table">
<% #jobs.each do |job| %>
<tr>
<td><%= job.organization %></td>
<td><%= job.location %></td>
<td><%= job.details %></td>
<td><%= job.start_date %></td>
<td><%= job.end_date %></td>
<td><%= link_to 'Show', job %></td>
<td><%= link_to 'Edit', edit_job_path(job) %></td>
<td><%= link_to 'Destroy', job, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
after all that it worked but I still hadn't DRY'd up the code so I removed the repeated section from index.html.erb which is in _job.html.erb (as shown above) and replaced it with this.
<%= render :partial => #jobs %>
and now it gives me two identical <tbody> tags with id="jobs_table". Why is this giving duplicate data?
You've got a lot to fix...
Create a nested route in your routes.rb:
resources :jobs
resources :categories do
resources :jobs
end
index.html.erb:
<h1>Listing jobs</h1>
<div>
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, category_jobs_path(category),
class: "category_link", remote: true %></li>
<% end %>
</ul>
</div>
<table>
<thead>
<tr>
<th>Organization</th>
<th>Location</th>
<th>Details</th>
<th>Start date</th>
<th>End date</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="jobs_table"><%= render partial: #jobs %></tbody>
</table>
<br/>
<%= link_to 'New Job', new_job_path %>
the index of jobs_controller.rb can (should) be refactored to:
class JobsController < ApplicationController
def index
#jobs = Job.where(category_id: params[:category_id] || 1)
respond_to do |format|
format.html
format.js
end
end
end
and the index.js.erb response also should be refactored to:
$("#jobs_table").html("<%= escape_javascript(render partial: #jobs) %>")
$("#jobs_table").fadeIn()
there are some naming issues which should be more pregnant like:
jobs instead of jobs_table
and
category instead of category_link
Also trying to find a Job belonging to Category with 1 is odd. Deal with a different response than a default Category with id 1 (hard coded ids are one of the worst things you can do).
The div around the Categories list is useless (keep your rendered HTML slim and readable).
The problem is due to not understanding when rails manipulates singular vs plural.
Calling render partial: #jobs automagically goes out to the partial _job.html.erb for each element in #jobs. But then the partial goes through each element again because of #jobs.each do |job|.
To fix it, in the render line, replace #jobs with "jobs" and rename _job.html.erb to _jobs.html.erb.
Alternatively, save a step by just replacing #jobs with "job" and keep the template name _job, but this reinforces an incorrect naming scheme.
index.html.erb:
<tbody id="jobs"><%= render partial: "jobs" %></tbody>
index.js.erb:
$("#jobs").html("<%= escape_javascript(render(partial: 'jobs'))%>")
Now it will just search literally for the _jobs template (_jobs.html.erb) and render it once as opposed to going to the singular version of the name and rendering that many times.

Render partial in new site, rails

Ok so far i created an new controller with:
rails g controller home settings
In the settings.html.erb i want to display an partial so that i simply added one line:
<%= render "categories/index", :locals => {:categories => #categories} %>
So my categories/_index.html.erb looks like this, and worked:
<% for category in #categories do %>
<tr>
<td><%= category.typ %></td>
<td><%= link_to "Löschen", category,:class => 'btn btn-mini btn-danger', method: :delete, data: { confirm: 'Sind sie sicher?' } %></td>
</tr>
<% end %>
<tr>
<%= form_for Category.new do |f| %>
<td> <%= f.text_field :typ, :class => "input-small" %></td>
<td><%= f.submit "Speichern", :class => 'btn btn-mini btn-success' %></td>
</tr>
<% end %>
</table>
</div>
But now when i open localhost:3000/home/settings i get the error:
NoMethodError in Home#settings
Showing C:/Sites/rublesql/app/views/categories/_index.html.erb where line #10 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #10):
7: <th></th>
8: </tr>
9:
10: <% for category in #categories do %>
11: <tr>
12: <td><%= category.typ %></td>
So my question is what did i wrong?
Categories controller:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def destroy
#category = Category.find(params[:id])
#category.destroy
redirect_to categories_path
end
def create
#category = Category.new(params[:category])
#category.save
redirect_to categories_path
end
end
It means the #categories instance variable hasn't been set.
Check in your controller that it sets #categories = xx.
Three things I notice:
You're mixing notations with the partial. Previously you would do, render partial: "x", locals: {}, now you can drop the partial key and just send the view path in, but if you choose to do this you also remove the locals: key:
<%= render "categories/index", {categories: #categories} %>
Also:
{:categories => #categories} will make categories your local, not #categories.
However, your instanced #categories should pass through as well, so it isn't your issue.
Finally:
#categories isn't set (or if it is, it becomes nil). Either make sure your controller correctly assigns it, or otherwise check .nil? or for .present? before attempting to loop through them.

link_to text - using ruby code for html text

I want the Link text on my view to display as Hospital, Country. Country is a guidelines attribute so I need to be able to access guidelines.country from 'hospital' and display it
e.g. Get Well Hospital, Sickland
I'm not sure how to code this correctly. At the moment in my view file I have
<% #list.each do |hospital| %>
<tr class="tablerow">
<td><%= link_to (hospital, country), :action => :topichospital, :hospital => hospital, :country=>country %></td>
</tr>
It worked when I just had, but I'm not sure how to add the country too
<% #list.each do |hospital| %>
<tr class="tablerow">
<td><%= link_to hospital, :action => :topichospital, :hospital => hospital %></td>
</tr>
my listhospital action in guidelines_controller.rb is
def listhospital
#list = Guideline.order(:hospital).uniq.pluck(:hospital)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #guidelines }
end
end
change your link_to to
<%= link_to "#{hospital}, #{country}", { :action => :topichospital, :hospital => hospital, :country=>country } %>
This will convert the first parameter passed to string. I'm not sure how rails interprets (hospital, country) in a link_to when passed as the first parameter but this will make sure to call the to_s methods for each.
UPDATE: IIRC, you can use pluck to combine attributes
# postgre
#list = Guideline.order(:hospital).uniq.pluck("hospital || ', ' || country")
# mysql
#list = Guideline.order(:hospital).uniq.pluck("CONCAT(hospital, ', ', country)")
then you can just use link_to hospital in the view.
UPDATE: This is becoming a bit of a hack. I suggest you change the controller to
#list = Guideline.select('hospital, country').order(:hospital).uniq
Then in your view
<% #list.each do |guideline| %>
<tr class="tablerow">
<td><%= link_to "#{guideline.hospital}, #{guideline.country}", { :action => :topichospital, :hospital => guideline.hospital, :country => guideline.country }%></td>
</tr>
<% end %>
I think you're looking for:
<%= link_to "#{hospital}, #{country}", :action => :topichospital, :hospital => hospital, :country=>country %>
You could also pass a block to link_to:
<%= link_to :action => :topichospital, :hospital => hospital, :country=>country do %>
<%= hospital %>, <%= country %>
<% end %>
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to

Trouble with deleting my blog posts using the UI

I am very new to Ruby on Rails so apologies, as this may be a silly question to post here.
I have made a blog (using generate scaffold). I have a few pages to interact and edit blog posts, starting with a main page which displays all blog posts ("index"), an area to view a specific blog post ("show"), and area to edit a blog post ("edit"), and an area to create a new blog post ("new").
I've also created comments (again using generate scaffold) to be applied to relevant blog posts. Comments, and a partial form for comments appears on the "show" page.
I have been working away on the whole thing to get it working nicely, but have recently realised that delete buttons that I had on the "index" page aren't working. Instead of prompting confirmation for the delete, I'm simply taken to the "show" of the relevant post.
Here is a snippet of the index "index" page:
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= image_tag "work/thumbnails/#{post.image}", :alt => '' %></td>
<td><%= time_ago_in_words(post.created_at) %> ago (<%= post.created_at %>)</td>
<td class="zero-out"><%= link_to 'Show', post, :class => "submit-button" %></td>
<td class="zero-out"><%= link_to 'Edit', edit_post_path(post), :class => "submit-button" %></td>
<td class="zero-out"><%= link_to 'Destroy', post, confirm: 'Are you sure?', :method => :delete, :class => "submit-button" %></td>
</tr>
<% end %>
And here is the snippet of code from the posts_controller relevant to the delete:
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :ok }
end
end
I have also found that the remove comment buttons (on the "show" page alongside each comment) have stopped working with an error message:
Unknown action
The action 'show' could not be found for CommentsController
For reference the code for the "remove comment" button is:
<%= link_to 'Remove Comment', [comment.post, comment],
:confirm => 'Are you sure?',
:method => :delete %>
And the snippet of code in the comments_controller is:
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
I lack the full knowledge of how RoR works, and how these files interact with each other fully to troubleshoot the problem, so any help would be very much appreciated.
First you miss the arrow in the destroy link method call
Correct it to this.
<%= link_to 'Destroy', post, confirm: 'Are you sure?', :method => :delete, :class => "submit-button" %>
Second you don't have to find the post of a comment to delete it simply do this.
If you want to be redirected back to the post, you do it in the controller
<%= link_to 'Remove comment', comment, confirm: 'Are you sure?', :method => :delete %>
in the comment_controller
def destroy
#comment = Comment.find(params[:id])
#post = #comment.post
#comment.destroy
respond_to do |format|
format.html { redirect_to #post }
format.json { head :ok }
end
end
I've found the problem - I had customised the links to stylesheets, javascript files etc and in doing this I had left out links to the javascript files for posts and comments created by the scaffold.
After including links to these files everything worked again.

does not find rjs file

I am using rails 2.3.8 and I'll load a modal dialog box using a partial called _show_venue.html.erb. Inside this partial I add link_to_remote to edit each venue.
_show_venue.html.erb ::
<table>
<tr>
<th>Country</th>
<th>Place</th>
<th>Color</th>
</tr>
<% #venues.each do |venue| %>
<tr>
<td><%=h venue.country_id %></td>
<td><%=h venue.place %></td>
<td><%=h venue.color %></td>
<td><%= link_to_remote 'Edit', :url => {:controller => 'venues', :action => 'edit', :id=>venue.id } %></td>
</tr>
<% end %>
</table>
And this is my controller code ::
def edit
#venue = Venue.find(params[:id])
end
edit.js.rjs ::
page.replace_html 'edit_venue', :partial => 'edit_form'
page<< "$j ('#event_actions').dialog({
title: 'Edit venue
modal: true,
width: 500,
close: function(event, ui) { $j ('#event_actions').dialog('destroy') }
});"
But when I run this, it could not find edit.js.rjs file. Why did this happen? Anyone can explain it?
You should do the following changes to you controller method:
respond_to do |format|
format.js
end
so that it will find the edit.js.rjs and render it.
Edit: The 404 HTTP status which was the main problem was because of a missing route.
A route to match venues/:id/edit should solve the problem.
Rename your file edit.js.rjs to edit.rjs
Edited
I think you have to do it other way as you want dynamic object #venue,
Try following
def edit
#venue = Venue.find(params[:id])
render :update do |page|
page.replace_html 'edit_venue', :partial => 'edit_form', :object => #venue
page<< "$j ('#event_actions').dialog({
title: 'Edit venue
modal: true,
width: 500,
close: function(event, ui) { $j ('#event_actions').dialog('destroy') }
});"
end
end
your link should be as follows [you have to write :method ]
<%= link_to_remote 'Edit', :url => {:controller => 'venues', :action => 'edit', :id=>venue.id }, :method=>'put' %>
you can also try 'post' if above doesn't work
rename edit.js.rjs to edit.js.erb
Add the following to the end of your edit method:
respond_to do |format|
format.js
format.html
end
restart your server

Resources