Rails 3.1 Jquery Ajax CRUD Operations - ajax

I am working on Rails 3.1 Jquery Ajax demo app listed here https://github.com/samnang/ajax_rails31_demo. I am trying to add code to delete comments. I have modified comments_controller.rb and added a destroy action. I also added a link to the app/views/_comment.html.erb to include a Destroy link. I am able to get the comment to delete and the comment count is decremented by 1, but the comment partial does not update removing the entry. Only upon page refresh does the page display correctly. Here is my code
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
respond_to :html, :js
def index
#comments = Comment.all
end
def create
#comment = Comment.new(params[:comment])
#comment.save
respond_with #comment, :location => comments_url
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_with #comment, :location => comments_url
end
end
app/views/comments/index.html.erb
<% title "Comments for Ajax in Rails 3.1" %>
<div id="comments_count"><%= comments_count %></div>
<div id="comments">
<%= render #comments %>
</div>
<h3>Add your comment:</h3>
<%= form_for Comment.new, :remote => true do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :content, "Comment" %><br />
<%= f.text_area :content, :rows => '12', :cols => 35 %>
</p>
<p><%= f.submit %></p>
<% end %>
app/views/comments/_comment.html.erb
<div class="comment">
<strong><%= comment.name %></strong>
<em><%= comment.created_at.strftime('%b %d, %Y at %I:%M %p') %></em>
<%= simple_format comment.content %>
<%= link_to "Destroy", comment,:remote => true, :confirm => "You Sure", :method => :delete %>
</div>
app/vews/comments/create.js.coffee
$('<%= escape_javascript(render(:partial => #comment))%>')
.appendTo('#comments')
.hide()
.fadeIn()
$('#new_comment')[0].reset()
$('#comments_count').html '<%= comments_count %>'
app/views/comments/destroy.js.coffee
$('#new_comment')[0].reset()
$('#comments_count').html '<%= comments_count %>'
The destroy jquery portion is where I believe I am messing up. How do I reload the partial to remove the deleted comment?

I have updated my example on Github to support destroy action. In your example you didn't remove dom element in your destroy.js.coffee. Check out full code on Github again or look at below snippets:
app/views/comments/_comment.html.erb
<div id=<%= dom_id(comment) %> class="comment">
<strong><%= comment.name %></strong>
<em>on <%= comment.created_at.strftime('%b %d, %Y at %I:%M %p') %></em>
<%= link_to "Remove", comment, :method => :delete, :remote => true %>
<%= simple_format comment.content %>
</div>
app/views/comments/destroy.js.coffee
$('#comments_count').html '<%= comments_count %>'
$('#<%= dom_id(#comment) %>')
.fadeOut ->
$(this).remove()

Related

ActionController::UrlGenerationError in Posts#edit No route matches {:action=>"show"

I have been stuck with this issue for too long now - so hoping someone might be able to tell me what I am doing wrong. I am trying to add a simple blog to my website, using rails ajax through the remote: true option - everything works fine apart from editing a post.
Everything has been generated via the scaffold command and I am under the impression that it actually should be working.
As mentioned, what does not work is the editing of a post.
Error that is returned:
ActionController::UrlGenerationError in Posts#edit
Showing ~/webapp-rails4/app/views/posts/_form.html.erb where line #2 raised:
No route matches {:action=>"show", :controller=>"posts", :locale=>#<Post id: 6, title: "blog post nummer 2", body: "så prøver vi igen", created_at: "2014-11-02 11:42:19", updated_at: "2014-11-02 11:42:19", image: "Sk_rmbillede_2014-06-23_kl._21.31.58.png">, :id=>nil, :format=>nil} missing required keys: [:locale, :id]
1: <% logger.debug 'form being rendered'%>
2: <%= form_for #post, remote: true do |f| %>
3:
4:
5: <div class="field">
app/views/posts/_form.html.erb:2:in _app_views_posts__form_html_erb__3358809483585932967_70366784059520'
app/views/posts/edit.js.erb:2:in _app_views_posts_edit_js_erb___2360131588799055390_70366783957680'
my edit link:
<%= link_to 'Edit', edit_post_path(post.id, locale: I18n.locale), remote: true %>
controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
respond_to :js, :html
def edit
logger.debug 'controller action edit'
respond_with(#post)
end
def create
#post = Post.new(post_params)
#post.save
#respond_with(#post)
end
def update
#post.update(post_params)
#respond_with(#post)
end
private
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body, :image)
end
edit.js.erb (I have tried multiple things here, this is what I have at the moment):
alert('this is edit.js.erb');
$('#post<%= #post.id %> #editPostModal').append("<%= escape_javascript(render 'form', object: #post) %>");
$('#post<%= #post.id %> #editPostModal').foundation('reveal', 'open');
_form.html.erb(seems to be what is throwing the error):
<% logger.debug 'form being rendered'%>
<%= form_for #post, remote: true, :multipart => true, authenticity_token: true do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.file_field :image %>
</div>
<div>
<%= f.label :remote_image_url, "or image URL" %><br>
<%= f.text_field :remote_image_url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
rake routes:
posts GET /:locale/posts(.:format) posts#index {:locale=>/en|dk/}
POST /:locale/posts(.:format) posts#create {:locale=>/en|dk/}
new_post GET /:locale/posts/new(.:format) posts#new {:locale=>/en|dk/}
edit_post GET /:locale/posts/:id/edit(.:format) posts#edit {:locale=>/en|dk/}
post GET /:locale/posts/:id(.:format) posts#show {:locale=>/en|dk/}
PATCH /:locale/posts/:id(.:format) posts#update {:locale=>/en|dk/}
PUT /:locale/posts/:id(.:format) posts#update {:locale=>/en|dk/}
DELETE /:locale/posts/:id(.:format) posts#destroy {:locale=>/en|dk/}

undefined local variable or method `comment' for #<#<Class:0xb6d2fd0>:0xc077dd8>

undefined local variable or method `comment' for #<#<Class:0xb6d2fd0>:0xc077dd8>
This is what my _comment.html.erb partial looks like
<div class="media">
<%= link_to '#', class: 'pull-left' do %>
<%= image_tag(comment.user.avatar.small.url) if comment.user.avatar? %>
<% end %>
<div class="media-body">
<small>
<%= comment.user.name %> commented <%= time_ago_in_words(comment.created_at) %> ago
<% if policy(comment).destroy? %>
| <%= link_to "Delete", [#topic, #post, comment], method: :delete %>
<% end %>
</small>
</div>
The create section of my comments_controller.rb
def create
#post = Post.find(params[:post_id])
#comment = current_user.comments.build(comment_params)
#comment.post = #post
authorize #comment
if #comment.save
redirect_to #post, notice: "Comment was saved successfully."
else
flash[:error] = "Error creating comment. Please try again."
render :new
end
end
and how I rendered in my posts#show view
<div>
<%= render :partial => "comments/comment", local: {comment: #comment} %>
</div>
You're not passing any locals to this partial:
<%= render :partial => "comments/comment" %>
You'd want to do this:
<%= render :partial => "comments/comment", :locals => { :comment => #comment } %>
Or use the shortcut:
<%= render 'comments/comment', :comment => #comment %>
You're declaring a local variable named comment in your _comment.html.erb partial.
You'll need to pass the #comment from your controller like this:
<%= render :partial => "comments/comment", locals: { comment: #comment } %>
Take a look at Layouts and Rendering Rails Guide for more info.

Rails submit remote form onclick of radio button

I have a form that submits when you chose a radio button (below). Currently the page refreshes when it submits and I'd like to use Jquery and remote submission so it doesn't refresh. Any idea where to start with this?
<%= simple_form_for(#order) do |f| %>
<%= f.input :orderstatus_id, :as => :radio, :label => false do %>
<% current_user.account.orderstatuses.order(:status_order).each do |os| %>
<p id="invoice-color-select">
<%= f.radio_button :orderstatus_id, os.id, :class => 'selector', :onclick => "this.form.submit();" %>
<%= f.label "#{os.name}", :style => "background: ##{os.color}", :class => 'status' %>
</p>
<% end %>
<% end %>
<div style="margin-top:20px">
<% if !current_user.account.has_plan? || current_user.account.plan_key== "ultra" %>
<a class="fancybox" href="#editstatus">Edit</a>
<% end %>
</div>
<% end %>
I added this into my view:
<%= f.radio_button :orderstatus_id, os.id, :class => 'selector', :onclick => "this.form.submit();" %>
You can see the :onclick portion here.

TinyMCE for rails 3.1

in show page, i will convert string into hash,
form.html.erb
<%= f.text_area :content, :rows => 20, :cols => 120 %>
<script type="text/javascript">
$(function() {
$('textarea').tinymce({
theme: 'advanced'
});
});
</script>
show.html.erb
<p>
<%= #page.content %>
</p>
<p>
<%= link_to "Edit", editcontent_path(#page), :class => "abutton" %> |
<%= link_to "Destroy", destroycontent_path(#page), :confirm => 'Are you sure?', :method => :delete %> |
<%= link_to "View All", admins_view_content_path %>
</p>
but my page following, code not convert
I have not used tinymce , but as per documentation what I understand is
If you want to add content to editor pass that to the text area
<%= text_area_tag :editor, #page.content , :class => "tinymce", :rows => 40, :cols => 120 %>
# you can pass configuration option to tinymce here
<%= tinymce %>
In Show page
<p>
<%= #page.content.html_safe %> #Apply html_safe function to interpret string as html
</p>
This works for me.
Optionally raw(#page.content) also works

Form validation after ajax request

I'm using Rails 3.2 and I'm making my first Ajax request.
This is my code:
def create
#post = Post.find(params[:post_id])
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
format.html {
redirect_to #post
}
format.js
else
format.html {
render 'posts/show'
}
format.js
end
end
end
So, I understand that I return a js template.
So, question 1: Is really a good idea to use this approach instead the standard sending json / receiving json in a $.ajax call?
My create.js.erb:
$(".commentlist").append("<%= escape_javascript(render(:partial => #comment)) %>");
Working perfectly.
But... how I validate the form? (Without ajax works perfectly).
I'm seeing that the js.erb is like the html.erb but with js instead of html (I still see this weird, I think that is easier to use controller.coffee, but I will learn this way too :)).
So question 2: How I validate ? I see that what I get in the ajax call is the entire html and my two action vars (#post and #comment).
Just that, I need to learn the Rails approach to do ajax :)
P.S: My _form.html.erb:
<%= form_for comment, :url => post_comments_path(comment.post), :remote => true do |f| %>
<% if comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being added:</h2>
<ul>
<% comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :post_id %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :url %>
<%= f.text_field :url %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p class="no-border">
<%= f.submit "Post", :class => "button" %>
</p>
<% end %>

Resources