I have a polymorphic association with dailyposts & comments in my rails app
Everything works fine in the database, but when I try to add Ajax to the Destroy Action (I used this tutorial http://railscasts.com/episodes/136-jquery-ajax-revised)
....it doesn't work unless I refresh the page. (but my alert works in destroy.js.erb)
I know my error is in destroy.js.erb
New to Rails...Please help :)
This is my code...
ROUTES
resources :dailyposts do
resources :comments
end
CONTROLLERS
##Dailyposts
class DailypostsController < ApplicationController
respond_to :html, :js
def show
#user = User.find_by_username(params[:username])
#dailypost = Dailypost.find_by_id(params[:id])
#commentable = #dailypost
#comments = #commentable.comments.arrange(:order => :created_at)
#comment = Comment.new
end
end
##Comments
class CommentsController < ApplicationController
before_filter :load_commentable
respond_to :html, :js
def create
#comment = #commentable.comments.create(params[:comment])
#comment.user = current_user
if #comment.save
respond_to do |format|
format.html { redirect_to #commentable }
format.js
end
else
redirect_to #commentable, notice: "Comment can't be blank."
end
end
def destroy
#comment = Comment.find(params[:id])
#commentable = #comment.commentable
if #comment.destroy
respond_to do |format|
format.html { redirect_to #commentable }
format.js
end
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
end
VIEWS
Dailypost show.html.erb
<div class="row-fluid">
<div class="span12">
<div>
<%= raw(dailypost_with_links(#dailypost)) %>
</div>
<%= render "comments/form" %>
<div id="comments">
<%= nested_comments #comments %>
</div>
</div>
</div>
_comment.html.erb
<section class="comments">
<div class ="user">
<%= link_to comment.user.username, comment.user %>
<%= comment.content %>
</div>
##Here I am passing remote: true for ajax
<% if current_user?(comment.user) %>
<%= link_to content_tag(:i, "", class: "icon-trash icons"), [#commentable, comment], method: :delete,
data: { confirm: "Are you sure?" },
title: "Delete", remote: true %> |
<% end %>
</section>
destroy.js.erb
##alert is working
alert('ajax works!');
$('#<%= dom_id(#comment) %>').remove();
LOGS
Started DELETE "/dailyposts/11/comments/133" for 127.0.0.1 at 2013-08-04 23:06:31 -0700
Processing by CommentsController#destroy as JS
Parameters: {"dailypost_id"=>"11", "id"=>"133"}
Dailypost Load (0.3ms) SELECT "dailyposts".* FROM "dailyposts" WHERE "dailyposts"."id" = ? ORDER BY dailyposts.created_at DESC LIMIT 1 [["id", "11"]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'sgFH2XeZWEXCcjxiAwgfXg' LIMIT 1
Comment Load (0.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = ? LIMIT 1 [["id", "133"]]
Dailypost Load (0.1ms) SELECT "dailyposts".* FROM "dailyposts" WHERE "dailyposts"."id" = 11 ORDER BY dailyposts.created_at DESC LIMIT 1
(0.1ms) begin transaction
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE (comments.ancestry like '133/%' or comments.ancestry = '133')
SQL (0.4ms) DELETE FROM "comments" WHERE "comments"."id" = ? [["id", 133]]
(2.3ms) commit transaction
Rendered comments/destroy.js.erb (0.7ms)
Completed 200 OK in 25ms (Views: 10.3ms | ActiveRecord: 3.9ms)
Try this:
Dailypost show.html.erb
<div id="comments">
<%= render #comments %>
</div>
_comment.html.erb
<div id="<%= dom_id(comment) %>">
<%= comment.content %>
</div>
create.js.erb
$('<%= escape_javascript(render(:partial => #comment))%>').appendTo('#comments').hide().fadeIn();
destroy.js.erb
$('#<%= dom_id(#comment) %>').remove();
The redirect is breaking the response. Try changing it to redirect_to( :back ) unless request.xhr?
The problem is in destroy.js.erb , the second line does not work because there is no id like edit_comment_1 of the format edit_comment_(:id).
In your _comment.html.erb, add an appropriate div with id that is used in your .js.erb
<section class="comment">
<div id="edit_comment_<%= comment.id %>">
<div class ="user">
<%= link_to comment.user.username, comment.user %>
<%= comment.content %>
</div>
<% if current_user?(comment.user) %>
<%= link_to content_tag(:i, "", class: "icon-trash icons"), [#commentable, comment], method: :delete,
data: { confirm: "Are you sure?" },
title: "Delete", remote: true %> |
<% end %>
</div>
</section>
Related
the thing, that i tried a lot of stuff is is not working at all, somehow i am having this kind of error in my terminal, when i do my post request from my form:
20:21:01 web.1 | Started POST "/bookings" for ::1 at 2023-02-19 20:21:01 +0100
20:21:01 web.1 | Processing by BookingsController#create as TURBO_STREAM
20:21:01 web.1 | Parameters: {"authenticity_token"=>"[FILTERED]", "booking"=>{"start_time"=>"2023-02-28", "end_time"=>"2023-03-08"}, "commit"=>"Schedule your appointment"}
20:21:01 web.1 | User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
20:21:01 web.1 | Completed 404 Not Found in 4ms (ActiveRecord: 0.9ms | Allocations: 2628)
20:21:01 web.1 |
20:21:01 web.1 |
20:21:01 web.1 |
20:21:01 web.1 | ActiveRecord::RecordNotFound (Couldn't find Game without an ID):
20:21:01 web.1 |
20:21:01 web.1 | app/controllers/bookings_controller.rb:38:in `set_game'
20:21:01 web.1 | Started GET "/games/37" for ::1 at 2023-02-19 20:21:01 +0100
20:21:01 web.1 | Processing by GamesController#show as HTML
So I have a Games_controller User created with the devise, and a Bookings_controller. And in my show page, I see my bookings option, but somehow, when I click the submit button, nothing happend, and i got the error that I shared before, and I am not sure why. And the thing, that i dont understand is why i am not having any kind of flags like if my booking is not being saved at all, or if it saved i should have some kind of flag. So after a lot of consideration i decided to ask here.
Because I am definint my games_id in the form of my _show.html.erb. So if anyone has a solution for it will be great
GAMES_CONTROLLER
class GamesController < ApplicationController def home
authorize Game end
def index
#games = Game.all
#games = policy_scope(Game) end
def new
#game = Game.new
authorize #game end
def create
#game = Game.new(game_params)
#game.user = current_user
if #game.save
redirect_to game_path(#game) # later to be changed in game_path(#game) when we have a show
else
render :new, status: :unprocessable_entity
end
authorize #game end
def show
#game = Game.find(params[:id])
#booking = Booking.new(game: #game)
authorize #game end
def edit
#game = Game.find(params[:id])
authorize #game end
def update
#game = Game.find(params[:id])
if #game.update(game_params)
redirect_to game_path(#game)
else
render :new, status: :unprocessable_entity
end
authorize #game end
def destroy
#game = Game.find(params[:id])
#game.destroy
redirect_to games_path
authorize #game end
private
def game_params
params.require(:game).permit(:price, :title, :description, :photo) end end
BOOKING_CONTROLLER
class BookingsController < ApplicationController before_action :set_game, only: [:create] before_action :set_booking, only: [:show]
def index
authorize Booking
#bookings = policy_scope(Booking)
puts "Number of bookings: #{#bookings.count}" end
def show
authorize #booking end
def create
puts "Params: #{params.inspect}"
#booking = Booking.new(booking_params.merge(game: #game, user: current_user))
authorize #booking
if #booking.save
flash[:notice] = "Booking was successfully created."
redirect_to #booking
else
flash[:alert] = "There was an error creating the booking."
redirect_to #game
end
Rails.logger.debug "Params: #{params.inspect}"
Rails.logger.debug "Game: #{#game.inspect}"
Rails.logger.debug "Booking: #{#booking.inspect}"
Rails.logger.debug "Booking params: #{booking_params.inspect}"
Rails.logger.debug "Current user: #{current_user.inspect}" end
private
def set_game
#game = Game.find(params[:game_id])
puts #game.inspect end
def set_booking
#booking = Booking.find(params[:id]) end
def booking_params
params.require(:booking).permit(:start_date, :end_date, :game_id) end
def set_dates
self.start_date = start_date.to_date
self.end_date = end_date.to_date end
end
GAMES - SHOW.HTML.ERB
<%= render 'shared/navbar' %>
<h1>Show</h1> <h2><%= #game.title %></h2> <%= cl_image_tag #game.photo.key,
width: 400, height: 300, crop: :fill %> <p><%= #game.description %></p> <p><%= #game.price %></p> <p><% #game.categories.each do |category| %> <%= category.name %> <% end %> </p>
<p><%= link_to 'Edit game listing', edit_game_path(#game) if policy(#game).edit?%></p> <p><%= link_to 'Delete game listing', game_path(#game), data: { turbo_method: :delete, turbo_confirm: "Are you sure?" }if policy(#game).edit?%></p> <p><%= link_to 'Back to games', games_path %></p>
<h1>BOOKINGS</h1>
<%= render partial: 'bookings/show', locals: { booking: #booking } %>
BOOKING _SHOW.HTML.ERB
<%= simple_form_for #booking, data: { controller: 'flatpickr' } do |f| %> <%= f.hidden_field :game_id, value: #game.id %> <%= f.input :start_time, as: :string, input_html: { data: { flatpickr_target: "startTime" } } %> <%= f.input :end_time, as: :string, input_html: { data: { flatpickr_target: "endTime" } } %> <%= f.submit 'RENT THE GAME', class: 'btn btn-primary' %> <% end %>
<h1>Booking Details</h1> <p><strong>Start date:</strong> <%= #booking.start_date %></p> <p><strong>End date:</strong> <%= #booking.end_date %></p>
<h1>Here Come the calendar</h1> <%= render partial: 'bookings/calendar', locals: { bookings: #bookings } %>
BOOKING _CALENDAR.HTML.ERB
<div id='calendar'></div> <% if #bookings.present? %> <% #bookings.each do |booking| %>
<%= booking.inspect %><br> # Add this line <% end %> <% else %> No bookings to display. <% end %>
<script> document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: [
<% if #bookings %>
<% #bookings.each do |booking| %>
{
title: '<%= booking.game.title %>',
start: '<%= booking.start_date %>',
end: '<%= booking.end_date %>',
color: 'red'
},
<% end %>
<% end %>
]
});
calendar.render(); }); </script>
<html lang='en'> <head>
<meta charset='utf-8' />
<script src='https://cdn.jsdelivr.net/npm/fullcalendar#6.1.4/index.global.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
});
</script> </head> <body>
<div id='calendar'></div> </body> </html>
Started POST "/users/3/tweets" for 127.0.0.1 at 2018-10-01 16:43:04 +0100
Processing by TweetsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"a4GACc9npDT1aXdadefb62NbUVbAxA11JBQ/NDkCcPOS0l7wyBbJmwvdPdwZ8rZryT6LmxoFxI9wfv2RloLQIQ==", "tweet"=>{"content"=>"hello"}, "commit"=>"Create Tweet", "user_id"=>"3"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ /Users/benherring/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
↳ app/controllers/tweets_controller.rb:23
(0.1ms) BEGIN
↳ app/controllers/tweets_controller.rb:26
Tweet Create (0.4ms) INSERT INTO "tweets" ("content", "created_at", "updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id" [["content", "hello"], ["created_at", "2018-10-01 15:43:04.707047"], ["updated_at", "2018-10-01 15:43:04.707047"], ["user_id", 3]]
↳ app/controllers/tweets_controller.rb:26
(1.7ms) COMMIT
↳ app/controllers/tweets_controller.rb:26
Rendering tweets/create.js.erb
Rendered tweets/create.js.erb (7.3ms)
Completed 500 Internal Server Error in 34ms (ActiveRecord: 2.9ms)
ActionView::Template::Error (Missing partial tweets/_index with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in:
* "/Users/benherring/twitter-clone/app/views"
* "/Users/benherring/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/devise-4.5.0/app/views"
):
11: <% if #tweet.errors.any? %>
12: refreshForm('<%= j render "tweets/new", user: #user, tweet: #tweet %>');
13: <% else %>
14: addTweet('<%= j render "tweets/index", tweet: #tweet %>');
15: refreshForm('<%= j render "tweet/new", user: #user, tweet: Tweet.new %>');
16: <% end %>
app/views/tweets/create.js.erb:14:in `_app_views_tweets_create_js_erb__1236688757229574759_70092102807800'
im trying to submit a form so that the page doesnt reload, with ajax. the form does work without ajax at the moment, but i want it to be better. ive looked at the rails documentation and on here and i cant get my head around it. ive made changes to the form, controller and made a create.js.erb file but no luck. thanks
class TweetsController < ApplicationController
before_action :authenticate_user!, :except => [:index]
def index
# #tweets = Tweet.all.order("created_at DESC")
#tweets = Tweet.paginate(page: params[:page], per_page: 7).order('created_at DESC')
#tweet = Tweet.new
#user = current_user
end
def show
#tweet = Tweet.find(params[:id])
end
def new
# #tweet = Tweet.new
# #user = current_user
end
def create
# #user = current_user
#user = User.find(params[:user_id])
#tweet = Tweet.new(tweet_params)
#tweet.user = #user
if #tweet.save
respond_to do |format|
format.html { redirect_to user_tweets_path }
format.js
end
else
respond_to do |format|
format.html { render 'tweets/index' }
format.js
end
end
# redirect_to user_tweets_path
end
def edit
#tweet = Tweet.find(params[:id])
end
def update
#tweet = Tweet.find(params[:id])
#tweet.update(tweet_params)
redirect_to tweets_path
end
def upvote
#tweet = Tweet.find(params[:id])
#tweet.upvote_by current_user
# redirect_to :tweets
if request.xhr?
head :ok
else
redirect_to tweets_path
end
end
def downvote
#tweet = Tweet.find(params[:id])
#tweet.downvote_by current_user
redirect_to :tweets
end
private
def tweet_params
params.require(:tweet).permit(:content)
end
end
<%= simple_form_for [ #user ,#tweet], remote: true, id: "form-submit" do |f| %>
<%= f.input :content, label: "Tweet" %>
<%= f.button :submit, class: "btn btn-primary" %>
<% end %>
function refreshForm(innerHTML) {
const newTweetForm = document.getElementById('new_tweet');
newTweetForm.innerHTML = innerHTML;
}
function addTweet(tweetHTML) {
const tweets = document.getElementById('tweets');
reviews.insertAdjacentHTML('beforeend', reviewHTML);
}
<% if #review.errors.any? %>
refreshForm('<%= j render "tweets/new", user: #user, tweet: #tweet %>');
<% else %>
addTweet('<%= j render "tweets/index", tweet: #tweet %>');
refreshForm('<%= j render "tweet/new", user: #user, tweet: Tweet.new %>');
<% end %>
<h1 class="title text-primary">Home</h1>
<div class="tweet-form">
<% if user_signed_in? %>
<%= render 'new',user:#user, tweet:#tweet %>
<% end %>
</div>
<br>
<div id="tweets">
<% #tweets.each do |tweet| %>
<div class="card">
<div class="card-description">
<h4><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
<p class="tweet-content"><%= tweet.content %></p>
<p><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
<%= link_to like_tweet_path(tweet), method: :put do %>
<p>Upvote <%= tweet.get_upvotes.size %>
<% end %>
<%= link_to dislike_tweet_path(tweet), method: :put do %>
Downvote <%= tweet.get_downvotes.size %></p>
<% end %>
</div>
</div>
<% end %>
</div>
<div class="pages">
<%= will_paginate #tweets,renderer: BootstrapPagination::Rails %>
</div>
config.action_view.embed_authenticity_token_in_remote_forms = true
The error you are getting is the javascript response to the form submitting. This line in particular:
addTweet('<%= j render "tweets/index", tweet: #tweet %>')
is the issue.
ActionView::Template::Error (Missing partial tweets/_index with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}
you must not have a app/views/_tweets file in your application
note that render "tweets/index" automatically adds an underscore to the beginning of the filename passed in so tweets/index becomes tweets/_index.
you need to add a partial (a view file with a leading underscore) that renders the index template
I think you got a typo in your js.erb
const tweets = document.getElementById('tweets');
reviews.insertAdjacentHTML('beforeend', reviewHTML);
did you mean tweets instead of reviews in the second line?
also in the js.erb
function refreshForm(innerHTML) {
const newTweetForm = document.getElementById('new_tweet');
newTweetForm.innerHTML = innerHTML;
}
But this will render a form inside the form, shouldn't you get the parent element for that. In your case is the class tweet-form.
Your logs show this error:
ActionView::Template::Error (Missing partial tweets/_index
That's caused by this code:
addTweet('<%= j render "tweets/index", tweet: #tweet %>');
Apparently, you don't have a partial called tweets/_index to render.
Could you create this file and make sure it's named _index not index?
i am getting an error with the best_in_place gem.
i want to edit my comments inside of the post show action since i render all comments there.
NoMethodError in Posts#show
Showing undefined method `erererer' for #<Comment:0x00007fc0ff1721c8>
comment view that i render in posts show page.
<!--<h3>there are <%#= pluralize(#comments.count, "comment") %></h3> -->
<% #comments.each do |comment| %>
<div class="media mb-5 ">
<% if comment.user.avatar.present? %>
<%= image_tag comment.user.avatar.url, class: 'rounded mr-3 d-flex', width: 42, height: 42%>
<% else %>
<%= random_avatar 42, "d-flex rounded mr-3"%>
<% end %>
<div class="media-body">
<div class="d-flex justify-content-between" />
<h5 class="mt-0"><a><%=link_to comment.user.username, user_path(comment.user) %></a></h5>
<p class="m-0 form-group">created at <%=time_ago_in_words(comment.created_at) %></p>
</div>
<%= best_in_place comment, comment.body, :as => :textarea %>
<% if current_user == comment.user %>
<span style="font-size: 15px;">
<%= link_to '', [comment.post, comment], method: :delete, data: {confirm: "sure?"}, class: ' btn btn-outline-danger btn-sm pull-right fa fa-trash-o' %>
<%= link_to '',edit_post_comment_path(comment.post, comment), class: 'btn btn-outline-warning btn-sm pull-right fa fa-pencil-square-o' %>
</span>
<% end %>
</div>
</div>
</section>
<%end%>
application.js
$(document).ready(function() {
/* Activating Best In Place */
$('.best_in_place').best_in_place();
});
comments_controller.rb
def update
if #comment.update(params[:comment].permit(:body))
format.html { redirect_to post_path(#post) }
format.json { head :ok }
else
format.html { render :action => "edit" }
format.json { respond_with_bip(#comment) }
end
end
comment.rb
class Comment < ApplicationRecord
belongs_to :post
belongs_to :user
validates :body, presence: true
end
post.rb
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
validates :title, presence: true, length: { minimum: 5 }
validates :body, presence: true, length: { minimum: 240 }
post.controller - add post controller code to question
class PostsController < ApplicationController
before_action :find_post, only: %i[destroy edit update comment_owner upvote downvote]
after_action :verify_authorized, only: [:edit, :update, :destroy, :create, :new]
layout '_app_nav'
def index
return redirect_to post_path(params[:post_id]) if params[:post_id]
return redirect_to user_path(params[:user_id]) if params[:user_id]
#post = Post.all.order('created_at DESC')
#posts = Post.all.order('created_at DESC')
#user = User.all
#posts = if params[:search]
else
Post.all.order('created_at DESC')
end
#comments = Comment.all
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_params)
authorize #post
if #post.save!
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
#user = #post.user
#comments = Comment.where(post_id: #post).order('created_at DESC').paginate(:page => params[:page], :per_page => 5)
end
def edit
authorize #post
end
def update
authorize #post
if #post.update(post_params)
redirect_to #post, notice: 'updated.'
else
render :edit
end
end
end
def destroy
#post = Post.find(params[:id])
authorize #post
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body, :user_id)
end
def find_post
#post = Post.find(params[:id])
end
UPDATE
This is the entire request that i get when trying to open posts#show
Started GET "/news/2" for 127.0.0.1 at 2018-07-30 03:12:49 +0200
(0.6ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by PostsController#show as HTML
Parameters: {"id"=>"2"}
Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
Rendering posts/show.html.erb within layouts/_app_nav
Rendered comments/_form.html.erb (27.1ms)
Comment Load (0.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 2 ORDER BY created_at DESC LIMIT $1 OFFSET $2 [["LIMIT", 5], ["OFFSET", 0]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
Rendered comments/_comment.html.erb (14.2ms)
Rendered posts/show.html.erb within layouts/_app_nav (442.2ms)
Completed 500 Internal Server Error in 509ms (ActiveRecord: 12.4ms)
ActionView::Template::Error (undefined method `erererer' for #<Comment:0x00007feba5717bc0>):
15:
16: <p class="m-0 form-group">created at <%=time_ago_in_words(comment.created_at) %></p>
17: </div>
18: <%= best_in_place comment, comment.body, :as => :textarea %>
19: <% if current_user == comment.user %>
20: <span style="font-size: 15px;">
21: <%= link_to '', [comment.post, comment], method: :delete, data: {confirm: "sure?"}, class: ' btn btn-outline-danger btn-sm pull-right fa fa-trash-o' %>
app/views/comments/_comment.html.erb:18:in `block in _app_views_comments__comment_html_erb___2232672375721569353_70325032812060'
app/views/comments/_comment.html.erb:5:in `_app_views_comments__comment_html_erb___2232672375721569353_70325032812060'
app/views/posts/show.html.erb:76:in `_app_views_posts_show_html_erb___2994099099531367002_70324990819000'
<%= best_in_place comment, comment.body, :as => :textarea %> should be <%= best_in_place comment, :body, :as => :textarea %>
I have a two forms inside my edit action, one is to update an item inside the item.rb model(which works fine)... and the other one is to create an image in a attachment.rb model. The problem is that it creates a row inside the db images with null values and does not save the actually image along with the correct values.
items_contoller.rb
def edit
#attachment = Attachment.new
end
this is the form for the image create:
<%= form_for #attachment, url: create_attachment_path(#attachment), :html => {:id => "form", :multipart => true }, method: :post do |form| %>
<% if #attachment.errors.any? %>
<div class="centerList">
<div id="error_explanation">
<h2><%= pluralize(item.errors.count, "error") %> <%= t 'store_item_edit_4' %></h2>
<% #attachment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</div>
</div>
<% end %>
<%= hidden_field_tag :item_id, value: #item.id %>
<div class="form-group">
<div class="text-center">
<label class="btn btn-primary"><%= t 'store_item_edit_5' %><span style="display:none;">
<%= form.file_field :image, multiple: true, id: "uploads" %></span></label>
<%= form.submit '', :style => "display: none;" %>
<% end %>
this is the route:
post "attachments/create"=> "attachments#create", :as => :create_attachment
attachments_controller.rb
def create
#attachment = Attachment.new(attachment_params)
respond_to do |format|
if #attachment.save
format.html { redirect_back fallback_location: root_path, notice: 'Image was successfully uploaded.' }
format.json { render :show, status: :created, location: #attachment }
else
format.html { render :new }
format.json { render json: #attachment.errors, status: :unprocessable_entity }
end
end
end
def attachment_params
params.require(:attachment).permit(:item_id, :account_id, :image)
end
and this is what I get inside the console... at some point as you can see I get a Unpermitted parameter: :image:
started POST "/attachments/create" for 127.0.0.1 at 2018-03-14 17:20:23 +0200
Processing by AttachmentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"6kgGVoUf2tlM2YdxZis6xavw//zC4azttYi4FFshgw4swiFUIOfb58hCtZxf0If2ihOXz3SCETQSnci6l1IFIA==", "item_id"=>"{:value=>44}", "attachment"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x007fc6e4acfb18 #tempfile=#<Tempfile:/var/folders/hq/pr4rt14n7s31v3f6292wtjm00000gn/T/RackMultipart20180314-4193-1jrij48.jpg>, #original_filename="image1.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"attachment[image][]\"; filename=\"image1.jpg\"\r\nContent-Type: image/jpeg\r\n">]}}
Store Load (0.5ms) SELECT "stores".* FROM "stores" WHERE "stores"."id" = $1 ORDER BY "stores"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: :image
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO "attachments" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-03-14 15:20:23.368574"], ["updated_at", "2018-03-14 15:20:23.368574"]]
(1.2ms) COMMIT
Redirected to https://localhost:3000/store/items/edit/44
Completed 302 Found in 8ms (ActiveRecord: 2.3ms)
Any ideas how to fix this:
You should add:
def attachment_params
params.require(:attachment).permit(:item_id, :account_id, image: {})
end
My problem is after I create a new record with ajax I get a NOMETHODERROR and I must reload the page to see the new record.
The Error I get in terminal.
Rendered time_entries/_time_entry.html.erb (3.4ms) Rendered
time_entries/create.js.erb (4.9ms) Completed 500 Internal Server Error
in 41ms (ActiveRecord: 4.4ms)
NoMethodError - undefined method `each' for nil:NilClass:
app/views/time_entries/_time_entry.html.erb:1:in '_app_views_time_entries__time_entry_html_erb___4086905375499854267_70174828432680'
What I do wrong?
time_entries_controller.erb
class TimeEntriesController < ApplicationController
...
respond_to :html, :js
def index
#time_entries = current_user.time_entries.all.order("date DESC")
#time_entries_days = #time_entries.group_by{ |t| t.date.beginning_of_day }
respond_with(#time_entry)
end
def create
#time_entry = TimeEntry.new(timeentry_params)
#time_entry.user_id = current_user.id
respond_to do |format|
if #time_entry.save
format.html { redirect_to #time_entry, notice: 'Arbeitszeit wurde eingetragen' }
format.json { render :show, status: :created, location: #time_entry }
format.js
else
format.html { render :new }
format.json { render json: #time_entry.errors, status: :unprocessable_entity }
format.js
end
end
end
...
_time_entry.html.erb
the partial
<% #time_entries_days.each do |day, time_entries| %>
<% if day.today? %>
<div class="column-12 list-group">Today, <%= l day, format: :dm %></div>
<% else %>
<div class="column-12 list-group"><%= l day, format: :dm %></div>
<% end %>
<ul class="lists">
<% time_entries.each do |time_entry| %>
<li class="list-item" id="time_entry_<%= time_entry.id %>">
<div class="list-item__content">
<h3 class="list-item__title">
<%= link_to time_entry.category.name, time_entry %>
<span><%= l time_entry.start_time, format: :hm %></span> - <span><%= l time_entry.end_time, format: :hm %></span>
</h3>
<p><%= time_entry.note %></p>
</div>
<span class="list-item__label"><%= time_entry.hours %>h</span>
</li>
<% end %>
</ul>
<% end %>
index.html.erb
<% if can? :create, TimeEntry %>
<%= link_to 'Add new Time Entry', new_time_entry_path, remote: true, class: 'btn btn-primary', :data => { :'popup-open' => 'popup-1' } %>
<% end %>
...
<div class="row" id="container_time_entries">
<%= render "time_entry" %>
</div>
create.js.erb for testing
I don't get an alert after I create a new time entry.
alert("HALLO");
create.js.erb normal
$('.modal-bg').hide();
$('.popup').fadeOut(350);
$('#container_time_entries').html("<%= j(render 'time_entry') %>");
You do not set the variable #time_entries_days in your create method, but you need it in your _time_entry.html.erb .
Set it and you should be good to go.