Ajax escape_javascript method does not delete previous rendered partial in Rails - ruby-on-rails

I'm new in Ruby on Rails so I decided to do railstutorial.org's tutorial. I stuck on chapter 12, listing 12.37-38. I converted all html.erb files into html.haml (in chapter 7). I want Ajax to replace partials after clicking Follow/Unfollow button but right now when I click e.g. Follow button, Unfollow button is appearing above Follow and this Follow button is not disappearing.
Sth like that: http://i.imgur.com/RjwTsUU.png.
After that when I'm clicking on upper button it successfully replaces rendering of Follow/Unfollow partials but the button above(in this case Follow) will be visible until page is refreshed. What I am doing wrong?
destroy.js.erb:
$("#follow_form").html("<%= escape_javascript(render 'users/follow' ) %>");
$("#followers").html('<%= #user.followers.count %>');
create.js.erb:
$("#follow_form").html("<%= escape_javascript(render 'users/unfollow' ) %>");
$("#followers").html('<%= #user.followers.count %>');
show.html.haml:
- provide(:title, #user.name)
.row
%aside.col-md-4
%section.user_info
%h1
= gravatar_for #user
= #user.name
%section.stats
= render 'shared/stats'
.col-md-8
= render 'follow_form' if logged_in?
- if #user.microposts.any?
%h3
Microposts (#{#user.microposts.count})
%ol.microposts
= render #microposts
= will_paginate #microposts
follow_form partial:
- unless current_user?(#user)
%div#follow_form
- if current_user.following?(#user)
= render 'unfollow'
- else
= render 'follow'
unfollow partial:
= form_for(current_user.active_relationships.find_by(followed_id: #user.id), html: { method: :delete}, remote: true) do |f|
= f.submit "Unfollow", class: "btn"
follow partial:
= form_for(current_user.active_relationships.build, remote: true) do |f|
%div
= hidden_field_tag :followed_id, #user.id
= f.submit "Follow", class: "btn btn-primary"
relationships_controller.rb:
class RelationshipsController < ApplicationController
before_action :logged_in_user
def create
#user = User.find(params[:followed_id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end

According to the chapter where this feature is described you aren't quite using the right syntax for the render call. It should be:
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
Note the extra brackets after the render call that wraps around 'users/unfollow' - the same is true for your other call:
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
Hope that helps.

Related

Rails Remote True Ajax ActionController::UnknownFormat

I have a mini-update method in my model that only updates one field, set up in a chart (so I see the form for each row). It works properly, but want it to update using AJAX to be able to do multiple updates quickly without waiting for a full page reload.
The cell looks like this:
<td style="min-width: 150px" id="goody_cell<%= blog.id %>">
<%= render partial: "admin/goody_cell", locals: { blog: blog } %>
</td>
With this as the partial:
<% if blog.variation_id %>
<%= Variation.find(blog.variation_id).name %>
<% end %>
<%= simple_form_for(blog, url: update_goody_path(blog), remote: true, method: :patch, authenticity_token: true) do |f| %>
<% variation_collection = [] %>
<% Variation.all.each do |lm| %>
<% variation_collection << ["#{lm.name}", "#{lm.id}"] %>
<% end %>
<div class="row text-left">
<div class="form-group col-12 mb-0 pb-0">
<%= f.input :variation_id, label: false, prompt: "Choose a Related Goody", input_html: { id: "lmFor" + blog.id.to_s, class: 'browser-default', onchange: "this.form.submit();" }, collection: variation_collection, required: false %>
</div>
</div> <!-- row -->
<% end %>
My blogs/update_goody.js.erb looks like this:
$('#goody_cell<%= blog.id %>').html('<%= j render partial: "admin/goody_cell", locals: { blog: #blog } %>');
And my controller method is like this:
def update_goody
#blog = Blog.friendly.find(params[:id])
if #blog.update!(blog_params)
respond_to do |format|
format.js
end
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
I have the route like this:
patch "blogs/:id/update_goody" => "blogs#update_goody", as: "update_goody"
When I try to update it, it does update the value, but before it renders the partial, I get an error saying:
ActionController::UnknownFormat - ActionController::UnknownFormat:
app/controllers/blogs_controller.rb:178:in `update_goody'
I've looked at SO posts like this but they all say that the error was fixed by adding remote: true, which I already have.
Can anyone help me get this working?
instead of remote: true, use local: false (Rails 6)
make sure you have both update_goody.html.erb and update_goody.js.erb in your views/blogs folder.
you dont have to add anything to update_goody.html.erb as its not rendering at all.
in your controller
def update_goody
#blog = Blog.friendly.find(params[:id])
if #blog.update!(blog_params)
respond_to do |format|
format.html
format.js
end
else
format.html { render :edit }
format.json { render json: #blog.errors, status: :unprocessable_entity }
end
end
note that format.html in respond_to block. it dosent matter you add it or not as you are set remote: true in your form
refer this
In my case i had to put redirect_to to render html
respond_to do |format|
format.js
format.html { redirect_to update_goody_path }
end

Why Ajax call is responding after a page refresh in rails 4?

Suppose I have defined my create action like this:
def create
#appointment = Appointment.find(params[:appointment_id])
#note = #appointment.notes.new(notes_params)
#note.user_id = current_user.id
respond_to do |format|
if #note.save
format.html { redirect_to appointment_path(#appointment), notice: "Saved successfully" }
format.js
else
format.html { render 'new', notice: "Try again" }
format.js
end
end
end
My create.js.erb is like this:
$("#note_field").html("<%= j render partial: 'note', locals: {note: #note} %>");
Here is my form:
<%= form_for([#appointment, #appointment.notes.build({user: current_user})], remote: true) do |f| %>
<div>
<% if #note && #note.errors.any? %>
<% #note.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
</div>
<div class="field">
<%= f.label :Description %><br>
<%= f.text_area :description, required: true %>
</div>
<div>
<%= f.submit class: "note-button" %>
</div>
<% end %>
Here, note is partial form. How to make it work without a page refresh?

First argument in form cannot contain nil

I tried to use Ajax request for creating a new object and this had been working very well. In my view file I used to set remote: true option for link_to and everything was fine.
Now I want to render my _form partial once the view file is loaded without a link, but just using a <%= render 'form' %>.
I don't understand why I am getting this error. Who can enlighten me what am I doing wrong?
views/tasks/index.html
<h3>Tasks database</h3>
<table>
<% #tasks.each do |task| %>
<tr class='tasks' id="task_<%= task.id %>">
<td>
<%= link_to user_task_path(current_user, task.id), method: :delete,
data: { confirm: 'Are you sure?' }, remote: true do %>
<i class="glyphicon glyphicon-trash"></i>
<% end %>
<a href="#" data-xeditable="true" data-pk="task" data-model='task' data-name='title'
data-url="/users/<%= current_user.id %>/tasks/<%= task.id %>" data-title="Enter title">
<i><%= task.title %></i>
</a>
</td>
</tr>
<% end %>
<tr>
<td><%= render 'form' %></td>
</tr>
</table>
controllers/tasks_controller.rb
class TasksController < ApplicationController
before_filter :authorize, only: [:edit, :new, :destroy]
def index
#tasks = current_user.tasks
end
def show
#task = Task.find(params[:id])
redirect_to users_path
end
def edit
#task = Task.find(params[:id])
end
def new
#task = Task.new
end
def create
#task = current_user.tasks.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to user_tasks_path(current_user) }
format.js
else
format.html { render action: 'new' }
format.js
end
end
end
def update
#task = Task.find(params[:id])
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to user_tasks_path(current_user), notice: 'Post successfully was updated.'}
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { head :no_content }
end
end
end
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to {|format| format.js }
end
private
def task_params
params.require(:task).permit(:title)
end
end
views/tasks/_form.html
<%= form_for [current_user, #task], remote: true do |f| %>
<%= f.text_field :title %>
<%= f.hidden_field :user_id, value: params[:user_id] %>
<%= f.submit %>
<% end %>
views/tasks/create.js
$('#new_task').remove();
$('#new_link').show();
$('.tasks').last().after("<%=j render partial: 'task', :locals => { :task => #task } %>");
setXeditable();
Here is my rake routes
Any help?
First argument in form cannot contain nil or be empty
You are rendering form in index page and you didn't set #task in index method.
You should set #task in index method
def index
#tasks = current_user.tasks
#task = Task.new
end

How to add post via ajax, to loop in rails

i have home page, which render all posts
= render 'posts/post'
welcome_controller.rb
def home
#user = User.all
if user_signed_in?
#posts = current_user.posts.all.page(params[:page]).per(25)
#post = current_user.posts.build
else
hello
end
end
and _post.html.haml
= div_for(#posts.each) do |p|
.content-wrap
%hr
%small= "Отправлено #{p.user.first_name} #{p.user.last_name}"
= image_tag(p.user.img_url, class: 'img-responsive thumbnail user-image-home')
%p.text-content= p.content
%small.text-muted= "Добавлено #{time_ago_in_words(p.created_at)} назад"
%br
- if user_signed_in?
= link_to "Удалить", p, method: :delete, remote: true, data: { confirm: 'Удалить?', 'confirm-button-text' => 'Удалить', 'cancel-button-text' => 'Нет', 'sweet-alert-type' => 'warning' }, class: 'btn btn-danger btn-xs', id: 'wow' if current_user.id == p.user_id
%hr
= paginate #posts
and create.js.erb
$("<%= escape_javascript(render #post) %>").appendTo(".content-wrap");
But it didnt work, in console i have a error like "undefined method each", i have no idea how to add a post, and i need to add it with all divs and styles to posts loop, not only text. Help.
I think for starters user_signed_in? is not returning true so #posts is nil. Try this to make sure #posts is always defined, it will be populated when your conditional is true.
def home
#user = User.all
#posts = []
if user_signed_in?
#posts = current_user.posts.all.page(params[:page]).per(25)
#post = current_user.posts.build
else
hello
end
end
There is a lot of unconventional code here, I'd recommend wizzing through this tutorial: http://railsforzombies.org/

undefined method `picture' for nil:NilClass using carrierwave

I am making a form in my rails application where people have the option of adding images and I am using 'carrierwave' but I am getting an undefined method error on the edit page. Here is the code for the form:
<%= title "Add Item to #{#todo_list.title}" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<%= form.file_field :picture %>
<% end %>
Here I can see the upload button and it is working fine but on the edit page I get the above stated error. Code for my edit page:
<%= title "Editing Todo Item" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<% end %>
<div class="row">
<div class="small-12 columns">
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, #todo_item), method: :delete, data: { confirm: "Are you sure?" }, class: "button radius expand alert" %>
</div>
<%= #todo_item.picture %>
</div>
Why is this showing an undefined method error. I tried creating a method in my todo_item model but its still showing the above error.
Controller for todo_item:
class TodoItemsController < ApplicationController
before_action :require_user
before_action :find_todo_list
before_action :set_back_link, except: [:index]
def index
go_back_link_to todo_lists_path
end
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
flash[:success] = "Added todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "There was a problem adding that todo list item."
render action: :new
end
end
def edit
#todo_item = #todo_list.todo_items.find(params[:id])
end
def update
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.update_attributes(todo_item_params)
flash[:success] = "Saved todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "That todo item could not be saved."
render action: :edit
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo list item was deleted."
else
flash[:error] = "Todo list item could not be deleted."
end
redirect_to todo_list_todo_items_path
end
def complete
#todo_item = #todo_list.todo_items.find(params[:id])
#todo_item.toggle_completion!
redirect_to todo_list_todo_items_path, notice: "Todo item updated."
end
def url_options
{ todo_list_id: params[:todo_list_id] }.merge(super)
end
private
def set_back_link
go_back_link_to todo_list_todo_items_path(#todo_list)
end
def find_todo_list
#todo_list = current_user.todo_lists.find(params[:todo_list_id])
end
def todo_item_params
params[:todo_item].permit(:content)
end
end
To display your image you should change
<%= #todo_item.picture %>
to
<%= image_tag(#todo_item.picture_url) %>

Resources