rails simple ajax request - ruby-on-rails

i have a problem with ajax request:
in my app i am trying to configure a simple rank system, and i set it up, but whan i click on rank button - i reload the page and rank is refreshed.
Help my realize that in ajax:
i done that:
in posts/show.html.erb i have that:
<div id='vote_update'>
<%= render 'vote/update' %>
</div>
in vote/_update.html.erb i have :
<% if can? :update, Vote %>
<%= form_for([#post, #post.vote], remote: true) do |f| %>
...
<%= f.submit "vote" %>
in vote/update.js.erb i have:
$('#vote_update').html("<%= j render('vote/update') %>");
and in vote_controller.rb i have:
def update
post = Post.find(params[:post_id])
vote = post.vote
...
respond_to do |format|
if vote.save
format.html {
redirect_to post_path(post),
:notice => "You vote counted!"
}
format.js
end
end
end
if i remove romete: true - everything goes right ( page is reload, i saw (:notice) "You vote counted!" and rating is updated, but if i put remote: true back, i saw nothing ( some mistakes in firebug console ) - but when i reload page - ratign is updated, nd i saw norml result - i think i madesome mistakes in redirecting or i dont know
help please

your ajax code will come in format.js block. where you can update the html where you are showing the rank.

change
respond_to do |format|
if vote.save
format.html {
redirect_to post_path(post),
:notice => "You vote counted!"
}
format.js
end
end
to
if vote.save
respond_to do |format|
format.html {
redirect_to post_path(post),
:notice => "You vote counted!"
}
format.js
end
end
Not sure though

Related

Rails remote: true undefined method in view

I have a Rails 5.0.2 app and I've managed to implement a user following system using the acts_as_follower gem. Everything works nicely, however, I'm running into some trouble adding ajax.
I'm getting the following error when clicking 'follow'
NoMethodError at /7/follow
==========================
> undefined method `followed_by?' for nil:NilClass
I have the following
users_controller.rb
def follow
user = User.find(params[:id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to user}
format.js
end
end
show.html.erb
...
<div id="follow">
<%= render partial: "users/following", locals: {user: #user} %>
</div>
...
_following.html.erb
<% if !#user.followed_by?(current_user) %>
<%= link_to follow_user_path(#user.id), remote: true do %>
<h4><span class="label label-primary">Follow</span></h4>
<% end %>
<% else %>
<%= link_to unfollow_user_path(#user.id) do %>
<h4><span class="label label-primary">Unfollow</span></h4>
<% end %>
<% end %>
I understand that I have no #user in my partial after creating the record and I can't work out how to pass it back in to the partial. Any help would be appreciated.
Silly me.
In the follow method I had this:
def follow
user = User.find(params[:id])
current_user.follow(user)
respond_to do |format|
format.html { redirect_to user}
format.js
end
end
but should have been
def follow
#user = User.find(params[:id])
current_user.follow(#user)
respond_to do |format|
format.html { redirect_to #user}
format.js
end
end
#user rather than user
your problem here is that in your controller you have user, without the "#" user is a variable that exist just in your controller method, and #user is an instance variable that can be accessed on the view.
So if you plan to use this on the view, you need to add "#" to the variable.

Delete method returning error after devise logout

I'm running into a problem that I'm not exactly sure how to fix.
I have a simple to do list application with AJAX functionality on methods such as 'new', 'create', 'complete', 'delete', as well as Devise authentication.
When I first enter a new session with a User, all of these methods work without a problem. Additionally, the tasks are saved to only the user account, which is perfect.
However, when I log out of an account, and then log back in, the delete method no longer works. I receive the following error:
ActiveRecord::RecordNotFound (Couldn't find Task with 'id'=)
My tasks_controller.rb is below:
class TasksController < ApplicationController
def index
#task = current_user.tasks.all
end
def new
#task = Task.new
respond_to do |format|
format.js
format.html
end
end
def create
#task = current_user.tasks.new(task_params)
#task.save
respond_to do |format|
format.html
format.js
end
end
def update
#task = current_user.tasks.find(params[:id])
#task.toggle :complete
#task.save
respond_to do |format|
format.html
format.js
end
end
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.js
format.html
end
end
private
def task_params
params.require(:task).permit(:id, :title, :complete)
end
end
I'm not exactly sure how to fix this problem. Would anyone have an idea on what is going wrong here?
EDIT:
I noticed that on my index page, I have a link to destroy the user's session at the top:
<%= link_to "Log Out", destroy_user_session_path, :method => :delete %>
I'm wondering if rails is having some trouble with this as both the logout link and the delete link are referencing the same method. If so, how can I change the name of the delete method for Task?
<div class="delete"><%= link_to "X", task_path(#task), method: :delete, remote: true %></div>
What is #task referencing? It looks to me like you've set #task to a collection #task = current_user.tasks.all.
Which would be why your delete method can't find a specific record to delete.
-EDIT-
Change #task in your index controller to #tasks as it is a collection.
In your view, do something like:
<% #tasks.each do |task| %>
<div><%= task.title %><div class="delete"><%= link_to "X", task_path(task), method: :delete, remote: true %></div></div>
<% end %>
The key here is that you have task_path(task) which is referencing a specific task id as opposed to task_path(#task) which is referencing a collection of tasks.

Keeping validation errors after redirect from partial back to the same page that has the partial

So I'm trying to get the errors from my form that is rendered as a partial inside my root_path. After I attempt to post it, and it fails (or succeeds), I want to redirect back to the root_path. However, redirect_to decides to not save any information for the validation.
Wondering how to do this.
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#nom = current_user.noms.build(params[:nom])
if #nom.save
flash[:success] = "Nom created!"
redirect_to root_path
else
flash[:error] = #nom.errors
redirect_to root_path
end
In my Home/Index, I render the partial for the form of the post.
= form_for [current_user, #post] do |f|
= f.text_field :name
= f.select :category
= f.text_area :description
= f.submit "Post", class: "btn btn-primary"
- #post.errors.full_messages.each do |msg|
%p
= msg
It should be keeping the errors at the bottom of the form after it redirects to the root_path.
I'd also like to keep the information that was there after the validation failed.
You should not use redirect in this case, instead use render:
class PostsController < ApplicationController
#..
def create
#nom = current_user.noms.build(params[:nom])
if #nom.save
flash[:success] = "Nom created!"
redirect_to root_path
else
flash[:error] = #nom.errors
render :template => "controller/index"
end
end
Replace controller/index with names of you controller and action
Also check this question
This seemed to work for me
format.html { redirect_to :back, flash: {:errors => "Document "+#requested_doc.errors.messages[:document][0] }}
I don't know if this could cause any other exception issues.
You can not use redirect_to for showing the error messages of an object because while redirecting it discards your object which does have linked with the error_messages & took a new object to redirect the path.
So in that case, you only have to use render.
respond_to do |format|
format.html {
flash[:error] = #account.errors.full_messages.join(', ')
render "edit", :id => #account._id, sid: #account.site._id
}
end

Rails: Redirect to show only after form submission

I'm following Ryan Bates' guide on search functionality. I've left out the implementation of the search algorithm right now, only returning So far it's doing what it should, the only problem is that now when I visit /posts, I get automatically redirected to /posts/1.
In my Posts controller:
def show
end
def index
#post = Post.search params[:search]
puts ("----------------" + #post.to_s + "-----------")
respond_to do |format|
format.html { redirect_to #post }
end
end
In my index.html.erb:
<%= form_tag posts_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
In my Posts.rb
def self.search(search)
#insert search method here
return Post.find_by_id(1)
end
How can I get this so that I can visit /posts and search in my form without being automatically redirected?
Once you flush out your Posts.search to do something real, that won't be the case. Instead, you'll get #posts = [] or #posts = nil sometimes (depending on what you're after), and that will be its own problem. In the long run I think you'll have to have branch logic similar to
respond_to do |format|
format.html { #post.present? ? redirect_to(#post) : render(:index) }
end
Also, not sure how Ryan Bates does it exactly, but I always find value in having an ActiveModel-based search model. If it stays simple don't worry about it, but it's nice to have that in your bag of tricks if search starts to turn into its own beast, ex. special validations, multiple-model searching, etc.
The only way from your implementation would be to check for params[:search]. This would be nil if you just went to /posts
respond_to do |format|
format.html { redirect_to #post if !params[:search].nil? }
end

Simple one model singular resource routing problem

I have a stripped down shopping cart application, currently with one model "cart", the cart id is stored in a session.
the cart controller has this method so we always have a cart
def initialize_cart
if session[:cart_id]
#cart = Cart.find(session[:cart_id])
else
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
my routes file has this one line
map.resource :cart
my cart/show view looks like this, i have added a form to it so that ultimately i can update the quantity of items, but for now i am just editing the created_at attribute.
<% form_for(#cart) do |f| %>
<%= f.date_select :created_at %>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>
<%= link_to 'Edit', edit_cart_path(#cart) %> |
<%= link_to 'Back', cart_path %>
and finally, my update action looks like this:
def update
##cart = Cart.find(params[:id])
respond_to do |format|
if #cart.update_attributes(params[:cart])
format.html { redirect_to(cart_path) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #cart.errors, :status => :unprocessable_entity }
end
end
end
when i make a change to "created_at" attribute on the "show" page, the attribute is successfully updated, but when i get redirected, i get a bizare url like this
http://192.168.0.10:3000/cart.%23%3Ccart:0x23d46fc%3E
I have fiddled with the update action, and can get the whole thing to work perfectly by doing this
# PUT /carts/1
# PUT /carts/1.xml
def update
##cart = Cart.find(params[:id])
#respond_to do |format|
if #cart.update_attributes(params[:cart])
redirect_to(cart_path)
# head :ok
#else
# render :action => "edit"
# render :xml => #cart.errors, :status => :unprocessable_entity }
end
#end
Its something to do with the respond_to block that is causing it to mess up, i would really appreciate any help i can get with this.
Thanks
For singular resource, you don't need to specify the object in the routes.
So you should use this:
<%= link_to 'Edit', edit_cart_path %>
===== UPDATED =====
I just found your real problem ^^" (but the original should be true too)
You used form_for(#cart) do |f|, which produced that ugly path
Please change to form_for(#cart, :url => cart_path) do |f|
I don't know why too, but it should be ok......

Resources