jQuery validate submit form ActionController::ParameterMissing - javascript

server log:
`ActionController::ParameterMissing (param is missing or the value is empty: comment)`
used pry gem gem params:
<ActionController::Parameters {"utf8"=>"✓", "comment_name"=>"123432",
"comment_description"=>"231424", "commit"=>"submit",
"controller"=>"comments", "action"=>"create", "article_id"=>"5"} permitted: false>
I know the :comment should wrapper coment_name and comment_description
so on validate add submitHandler try fix the format error
click submit button the browser show:
jquery validate:
$(function () {
$("form#new_comment").validate({
rules: {
comment_name: {
required: true,
minlength: 3
},
comment_description: {
required: true,
minlength: 5
},
submitHandler: function (form) {
$.ajax({
url: form.action,
type: form.method,
data: $(form).serializeArray(),
dataType: 'script'
});
}
}
});
});
_form.html.erb:
<%= simple_form_for [#article, #article.comments.build], remote: true do |f| %>
<%= f.input :name, input_html: { name: "comment_name"} %>
<%= f.input :description, input_html: { name: "comment_description" } %>
<%= f.submit :submit, class: "btn btn-default" %>
<% end %>
comment_controller:
class CommentsController < ApplicationController
before_action :get_article
before_action :authenticate_user!
def create
#comment = #article.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
respond_to do |format|
format.html { redirect_to #article, notice: "creaed succeed"}
format.js { }
end
else
redirect_to #article, notice: "characters is too short or name has been taken"
end
end
def destroy
#comment = #article.comments.find(params[:id])
if #comment.destroy
respond_to do |format|
format.html { redirect_to #article }
format.js { }
end
end
end
private
def comment_params
params.require(:comment).permit(:name, :description, :article_id, :user_id)
end
def get_article
#article = Article.find(params[:article_id])
end
end
any help thank 🙃

The controller expects
<ActionController::Parameters {"utf8"=>"✓", "comment"=>
{name"=>"123432","description"=>"231424"}, "commit"=>"submit",
"controller"=>"comments", "action"=>"create", "article_id"=>"5"}
permitted: false>
In your form, by declaring "name" attributes for the 'name' and 'description' fields, you are essentially overwriting the "name" field's name from comment[name] to comment_name. So just remove those name attributes from your form
<%= simple_form_for [#article, #article.comments.build], remote: true do |f| %>
<%= f.input :name%>
<%= f.input :description%>
<%= f.submit :submit, class: "btn btn-default" %>
<% end %>`

Related

Is there a way to add new values to a collection_select field in a form in Rails 6?

In my blog app, there are posts and each post can optionally have tags. When the user is on the new or edit post form, they currently have the means to select or deselect tags to associate with the post. There is a many-to-many relationship between the post and tag models and I am using bootstrap, bootstrap_form and bootstrap-select. This all works seemingly very well. The problem is, when the user is assigning tags to their post, these tags currently have to already exist (otherwise they would have to abort their post and go add tags...bad user experience). I am trying to devise a way to give the user the option to create new tags and/or select already-existing tags and apply them to the post, all on the same post form in the collection_select field, all at the same time.
Apparently I'm asking the wrong questions on google...wouldn't this be a common need, already solved?
I am asking for guidance in providing an 'add new tag' functionality to an otherwise functional collection_select field. How best to go about this?
Posts Controller:
class PostsController < ApplicationController
before_action :set_post, only: %i[edit update interim destroy]
# GET /posts
# GET /posts.json
def index
if user_signed_in? && current_user.admin_role
if params[:tag]
#posts = Post.tagged_with(params[:tag]).all.order('updated_at DESC').page params[:page]
else
#posts = Post.all.order('updated_at DESC').page params[:page]
end
else
if params[:tag]
#posts = Post.tagged_with(params[:tag]).where(published: true).order('updated_at DESC').page params[:page]
else
#posts = Post.where(published: true).order('updated_at DESC').page params[:page]
end
end
end
# GET /posts/new
def new
#post = current_user.posts.build
#categories = Category.pluck(:name, :id)
end
# GET /posts/1/edit
def edit
#categories = Category.pluck(:name, :id)
#cat = #post.category_id
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.create(post_params)
respond_to do |format|
if #post.save
if params[:interim]
format.html { redirect_to edit_post_path(#post), notice: 'Post was successfully created.' }
format.json { redirect_to edit_post_path(#post), status: :created, location: #post, notice: 'Post was successfully created.' }
elsif params[:complete]
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
end
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
if params[:interim]
format.html { redirect_to edit_post_path(#post), notice: 'Post was successfully updated.' }
format.json { redirect_to edit_post_path(#post), status: :ok, location: #post, notice: 'Post was successfully updated.' }
elsif params[:complete]
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
end
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content, :user_id, :published, :category_id, :tag_list, :tag, { tag_ids: [] }, :tag_ids,
comment_attributes: [:id, :title, :user_id, :content, :post_id, :parent_id, :ancestry, :commentable, :commentable_id, :commentable_type])
end
end
No tags controller (not needed thus far)
Post Model:
class Post < ApplicationRecord
has_many :taggings
has_many :tags, through: :taggings
has_rich_text :content
include PgSearch::Model
multisearchable :against => [:title, :content]
def self.published(post)
post.published
end
def self.tagged_with(name)
Tag.find_by!(name: name).posts
end
def self.tag_counts
Tag.select('tags.*, count(taggings.tag_id) as count').joins(:taggings).group('taggings.tag_id')
end
def tag_list
tags.map(&:name).join(', ')
end
def tag_list=(names)
self.tags = names.split(',').map do |n|
Tag.where(name: n.strip).first_or_create!
end
end
end
Tag Model:
class Tag < ApplicationRecord
has_many :taggings
has_many :posts, through: :taggings
end
Tagging Model:
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :post
end
Post Form Partial (the actual new and edit views do nothing but render this form):
<%= bootstrap_form_for #post, local: true, html: { class: 'form-horizontal' } do |f| %>
<%= f.text_field :title %>
<%= f.rich_text_area :content, control_class: 'trix-content-edit' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
<%= f.form_group :published, label: { text: "Publication Status" } do %>
<%= f.radio_button :published, true, label: "Published" %>
<%= f.radio_button :published, false, label: "Draft" %>
<% end %>
<%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, {label: 'Tags', include_blank: true}, {class: 'selectpicker show-tick', multiple: 'multiple', title: 'Make your selection...', 'data-live-search': 'true', 'data-actions-box': 'true'} %>
<br><br>
<%= f.submit "Save and Resume Editing", name: "interim", class: "btn btn-primary" %>
<%= f.submit "Save and Quit", name: "complete", class: "btn btn-primary" %>
<br><br>
<% end %>
No forms for tag at this time.

Rails submitting a form through ajax

There is some problem with using ajax in rails. I want to create new post in my wellcome/inex page. But when I push the botton it show
No route matches [POST] "/welcome/index"
wellcome/index.html
<b>Projects</b>
<ul id="projects">
<% #projects.each do |project| %>
<h2><%= project.title %></h2>
<% end %>
</ul>
<br>
<%= form_for :project do |f| %>
<%= f.text_field :title, :placeholder => ' Enter new project here..' %>
<but><%= f.submit 'Add Project'%></but>
<% end %>
welcome_controller.rb
class WelcomeController < ApplicationController
def index
#projects = Project.all
#project = Project.new
end
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'project was successfully created.' }
format.js
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
private
def project_params
params.require(:project).permit(:title)
end
end
create.js.erb
$('#projects').html("<%= escape_javascript (render 'projects') %>");
routes project
Prefix Verb URI Pattern Controller#Action
project_index GET /project(.:format) project#index
POST /project(.:format) project#create
new_project GET /project/new(.:format) project#new
edit_project GET /project/:id/edit(.:format) project#edit
project GET /project/:id(.:format) project#show
PATCH /project/:id(.:format) project#update
PUT /project/:id(.:format) project#update
DELETE /project/:id(.:format) project#destroy
Spent a lot of time updating this with AJAX but failed everytime. Any there to help? Thanks in advance
You have to add remote: true into form.
<%= form_for #project, url: project_index_path, remote: true do |f| %>
<%= f.text_field :title, :placeholder => ' Enter new project here..' %>
<but><%= f.submit 'Add Project'%></but>
<% end %>
If you want integrate Ajax and Ruby you need to add the line below inside your link action
remote:true
also you can check this about Ajax and Ruby
How Ajax works with ruby on rails

Why is the link_to submitting form twice?

I am trying to use JavaScript with jquery in rails to update a div without reloading the page. Its working but the comment is being created twice. I know something is wrong in the form partial but couldn't figure it out. Any help?
The following are the files -
_new_comment.html.erb
<%= form_for [:home, Comment.new], :url => home_comments_path, :html => {:id => "comment-new-" + post.id.to_s} do |f| %>
<div>
<%= f.text_area :message, :class => "message-area-" + post.id.to_s, :placeholder => "Add comment..." %>
<%= f.hidden_field :post_id, :value => post.id %>
<span class="new-comment"><%= link_to 'Add', '#', remote: true, :onclick => "$('#comment-new-#{post.id}').submit()" %></span>
</div>
<% end %>
comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:notice] = 'Comment added sucessfully'
respond_to do |format|
format.html { redirect_to home_posts_url }
format.js
end
end
end
create.js.erb
$("#comment-new-83").before('<div class="notice"><%= escape_javascript(flash[:notice]) %></div>');
$("#comment-new-83")[0].reset();
home.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
$(document).ready(function() {
$("#comment-new-83").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
})
})
form_for will automatically post to the controller. You need not submit the form explicitly using jquery.
Reference

Rails: Capturing error messages in JavaScript

I am using ajax for creating post that belongs to a particular topic where I render the form in post index page. Each post can have many tags and I am also using devise authentication and CanCanCan authorization.
I need to capture the error message of the post submit and show it in the browser through this JavaScript template Create.js.erb with custom error messages instead of doing in post form.
Below is the code:
Post controller
class PostsController < ApplicationController
load_and_authorize_resource
before_action :set_post, only: [:show, :edit, :update, :destroy, :update_status]
skip_before_action :verify_authenticity_token
# GET /posts
# GET /posts.json
def index
if params[:topic_id].present?
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.paginate(page: params[:page], per_page: 10)
#post = #topic.posts.new
else
#posts = Post.eager_load(:topic, :user).paginate(page: params[:page], per_page: 10)
end
#tags =Tag.all
end
# GET /posts/1
# GET /posts/1.json
def show
#tags = #posts.tags
end
def update_status
current_user.posts<<(#posts)
end
# GET /posts/new
def new
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.new
#tags =Tag.all
end
# GET /posts/1/edit
def edit
#tags = #posts.tags
end
# POST /posts
# POST /posts.json
def create
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.create(post_params)
respond_to do |format|
#posts.user_id = current_user.id
if #posts.save
format.html { redirect_to topic_posts_path(#topic), notice: 'Post was successfully created.' }
format.js
format.json { render :show, status: :created, location: #posts }
else
format.html { render :new }
format.json { render json: #posts.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
#tags = #posts.tags
respond_to do |format|
if params[:rate].to_i>0
#posts.ratings.create(:star => params[:rate])
format.html { redirect_to post_path(#posts), notice: 'Rating was successfully updated.' }
elsif #posts.update(post_params)
format.html { redirect_to post_path(#posts), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #posts }
else
format.html { render :edit }
format.json { render json: #posts.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#posts.destroy
respond_to do |format|
format.html { redirect_to topic_posts_url(#posts.topic_id), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#posts = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:image, :name, :message, :topic_id, {tag_ids:[]}, :rate, :user_id)
end
protected
def json_request?
request.format.json?
end
end
post form
<%= form_for [#topic, #post], remote: 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 |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<div class="field">
<%= f.label :Image %><br>
<%= f.file_field :image %>
</div>
<div class="field">
<%= f.label :Name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :Message %><br>
<%= f.text_area :message %>
</div>
<% if #tags %>
<% #tags.each do |tag| %>
<div>
<%= check_box_tag "post[tag_ids][]", tag.id, #post.tags.include?(tag) %>
<%= tag.name %>
</div>
<% end %>
<% end %>
<br><br>
<%= link_to 'Create Tag', tags_path %>
<br><br>
<%= f.submit %>
<% end %>
create.js.erb
$("#post_table").append("<%= j render #posts %>");
alert("Post created")
index.html.erb
<p id="notice"><%= notice %></p>
<div id='ajax_loader' style="position: absolute; left: 50%; top: 50%; display: none;">
<%= image_tag "ajax-loader.gif" %>
</div>
<script>
$(document).ajaxStop(function(){
$("#ajax_loader").hide();
});
$(document).ajaxStart(function(){
$("#ajax_loader").show();
});
</script>
<%= will_paginate %>
<h1>Listing Posts</h1>
<table id = "post_table">
<thead>
<tr>
<th><th>Name</th></th>
<th><th>Author</th></th>
<th><th>Message</th></th>
<th><th>Status</th></th>
<th colspan="4"></th>
</tr>
</thead>
<tbody>
<%= render #posts %>
</tbody>
</table>
<br>
<% if #topic %>
<%= link_to 'New Post', "#", id: "new_post" %>|
<section id = "new_post_section">
<%= render 'form' %>
</section>
<%= link_to 'Back to Topics', topic_path(#topic) %>
<% else %>
<% link_to 'New Post', new_post_path %>
<% end %>
<%= will_paginate %>
Post model
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :topic
has_many :comments
has_and_belongs_to_many :tags
has_many :ratings
validates_presence_of :name, :presence => true
validates_length_of :name, maximum: 5
has_attached_file :image
#validates_attachment_presence :image, :presence => true
validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/png']
validates_attachment_size :image, :in => 0..100.kilobytes
end
Please help me.
Modify your the create action in the posts_controller.rb to something like this (notice that format.js was added to the else clause of the respond_to block):
# POST /posts
# POST /posts.json
def create
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.create(post_params)
respond_to do |format|
#posts.user_id = current_user.id
if #posts.save
format.html { redirect_to topic_posts_path(#topic), notice: 'Post was successfully created.' }
format.js
format.json { render :show, status: :created, location: #posts }
else
format.html { render :new }
format.js # call create.js.erb on save errors
format.json { render json: #posts.errors, status: :unprocessable_entity }
end
end
end
Then, in create.js.erb you can check for errors and handle them however you'd like. Example:
<% if #post.errors.any? %>
alert("ERROR(S): <%= j #post.errors.full_messages.join('; ') %>")
<% else %>
$("#post_table").append("<%= j render #posts %>");
alert("Post created");
<% end %>

Javascript voting acts_as_votable

I have a rails app, in which my Posts model has Comments and the comments are votable. I'm using acts_as_votable.
I currently have the voting on the comments working. Now I'm trying to implement some javascript so that the page does not have to refresh every time someone votes on a comment, so that the vote goes through.
Here is what I had before(which was working):
In my comments controller:
def upvote_post_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.liked_by current_user
respond_to do |format|
format.html {redirect_to :back}
end
end
And in my view:
<% if user_signed_in? && current_user != comment.user && !(current_user.voted_for? comment) %>
<%= link_to image_tag(‘vote.png'), like_post_comment_path(#post, comment), method: :put %> <a>
<%= "#{comment.votes.size}"%></a>
<% elsif user_signed_in? && (current_user = comment.user) %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% else %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% end %>
And this is what I now have:
In my comments controller:
def upvote_post_comment
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.liked_by current_user
respond_to do |format|
format.html {redirect_to :back }
format.json { render json: { count: #comment.liked_count } }
end
end
And in my view:
<% if user_signed_in? && current_user != comment.user && !(current_user.voted_for? comment) %>
<%= link_to image_tag(‘vote.png'), like_post_comment_path(#post, comment), method: :put, class: 'vote', remote: true %>
<a><%= "#{comment.votes.size}"%></a>
<script>
$('.vote')
.on('ajax:send', function () { $(this).addClass('loading'); })
.on('ajax:complete', function () { $(this).removeClass('loading'); })
.on('ajax:error', function () { $(this).after('<div class="error">There was an issue.</div>'); })
.on('ajax:success', function (data) { $(this).html(data.count); });
</script>
<% elsif user_signed_in? && (current_user = comment.user) %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% else %>
<%= image_tag(‘voted.png')%><a><%= "#{comment.votes.size}"%></a>
<% end %>
This shows me the error message: "There was an issue"
And when I refresh the page, I see that the vote went through and I see this in my terminal:
Started PUT “/1/comments/1/like" for 127.0.0.1 at 2014-04-06 18:54:38 -0400
Processing by CommentsController#upvote_post_comment as JS
Parameters: {"post_id"=>”1”, "id"=>”1”}
How do I get the voting to work via Javascript? So that the vote goes through, the vote count updates and the vote icon updates to voted.png instead of vote.png?
Your log says the request is formatted as JS.
Processing by CommentsController#upvote_post_comment as JS
Add data: { type: :json } to the link_to method to request a JSON format like so,
<%= link_to image_tag('vote.png'), like_post_comment_path(#post, comment), method: :put, class: 'vote', remote: true, data: { type: :json } %>
This will tell the controller you want a JSON response not a Javascript response.
Edit - updates from the comments.
Update controller to use,
format.json { render json: { count: #comment.likes.size } }
Update JS to use,
.on('ajax:success', function(e, data, status, xhr) { $(this).html(data.count); });

Categories

Resources