I am following a tutorial and we are creating a partial to to display a collection of data, but it is not rendering, my rails server command prompt shows that the database transaction is succesful:
Started GET "/portfolios" for ::1 at 2019-05-09 11:52:03 -0500
Processing by PortfoliosController#index as HTML
Rendering portfolios/index.html.erb within layouts/portfolio
Portfolio Load (0.3ms) SELECT "portfolios".* FROM "portfolios"
↳ app/views/portfolios/index.html.erb:5
Rendered collection of portfolios/_portfolio_item.html.erb [11 times] (2.1ms)
Rendered portfolios/index.html.erb within layouts/portfolio (5.3ms)
Rendered shared/_nav.html.erb (0.8ms)
Completed 200 OK in 31ms (Views: 28.6ms | ActiveRecord: 0.3ms)
Here is my partial under portfolios/_portfolio_item.html.erb:
<p><%= link_to portfolio_item.title, portfolio_show_path(portfolio_item) %></p>
<p><%= portfolio_item.subtitle %></p>
<p><%= portfolio_item.body %></p>
<%= image_tag portfolio_item.thumb_image unless portfolio_item.thumb_image.nil? %>
<%= link_to "Edit", edit_portfolio_path(portfolio_item) %>
<%= link_to 'Delete Portfolio Item', portfolio_path(portfolio_item), method: :delete, data: { confirm: 'Are you sure?' } %>
My index view under portfolios/index.html.erb :
<h1>Portfolio Items</h1>
<%= link_to "Create New Item", new_portfolio_url %>
<%= render partial: 'portfolio_item', collection: #portfolio_items %>
And my portfolios_controller :
class PortfoliosController < ApplicationController
layout 'portfolio'
def index
#portfolio_items = Portfolio.all
end
def show
#portfolio_item = Portfolio.find(params[:id])
end
def new
#portfolio_item = Portfolio.new
3.times { #portfolio_item.technologies.build }
end
def create
#portfolio_item = Portfolio.new(portfolio_params)
respond_to do |format|
if #portfolio_item.save
format.html { redirect_to portfolios_path, notice: 'Your portfolio item is now live!' }
else
format.html { render :new }
end
end
end
def edit
#portfolio_item = Portfolio.find(params[:id])
end
def update
#portfolio_item = Portfolio.find(params[:id])
respond_to do |format|
if #portfolio_item.update(portfolio_params)
format.html { redirect_to portfolios_path, notice: 'The record was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
#portfolio_item = Portfolio.find(params[:id])
#portfolio_item.destroy
respond_to do |format|
format.html { redirect_to portfolios_url, notice: 'Portfolio was successfully destroyed.' }
end
end
private
def portfolio_params
params.require(:portfolio).permit(:title,
:subtitle,
:body,
:main_image,
:thumb_image,
technologies_attributes: [:name])
end
end
If there is anything further needed please let me know and thanks in advance!
I'm not familiar with the collection syntax bbut for a quick fix try:
## index.html.erb
<h1>Portfolio Items</h1>
<%= link_to "Create New Item", new_portfolio_url %>
<% #portfolio_items.each do |item| %>
<%= render partial: 'portfolio_item', portfolio_item: item %>
<% end %>
Or if you really want to be fancy, and your model is called Portfolio, rename your partial to portfolios/_portfolio.html.erb. That will let you do:
## index.html.erb
<h1>Portfolio Items</h1>
<%= link_to "Create New Item", new_portfolio_url %>
<% #portfolio_items.each do |item| %>
<%= render item %>
<% end %>
Make sure there is no CSS or javascript that is removing/hiding your views. Also make sure you actually have some instances(rows) of the portfolio in your database.
<%= render partial: 'portfolio_item', collection: #portfolio_items %>
Although your usage of collection in partial is correct you can try to pass local variables and see if it works, because collection usage is dependent on file/model names which could cause issues.
When you use collection: #portfolio_items then you get access to use #portfolio_items instance variable within the partial view (portfolios/_portfolio_item.html.erb in your case).You are passing #portfolio_items but not using it anywhere, instead you are using portfolio_item variable which is not available in the partial view.
You need to iterate over #portfolio_items in order to render your items. If you need to pass variables to your partial use locals. Update your portfolios/index.html.erb as below
<h1>Portfolio Items</h1>
<%= link_to "Create New Item", new_portfolio_url %>
<% #portfolio_items.each do |portfolio_item| %>
<%= render partial: 'portfolio_item', locals: { portfolio_item: portfolio_item } %>
<% end %>
Related
I am using Hotwire Turbo Frame to create new record. My understanding was that when we create new record using Turbo Frame then only that single record will be replaced in index page rather than fetching all records from server. But when I look into Network tab, it returns all records from database. Only thing that it doesn't return is <head></head> content as expected. If it will return all record from database then it's not going to be fast. I most be doing something wrong. Below are my code snippets.
Controller
class QuotesController < ApplicationController
def index
#quotes = Quote.all
end
def new
#quote = Quote.new
end
def create
#quote = Quote.new(quote_params)
if #quote.save
respond_to do |format|
format.html { redirect_to root_path, notice: 'Success' }
format.turbo_stream
end
else
render :new, status: :unprocessable_entity
end
end
end
(more code here ....)
View (index.html.erb)
<h1>Quotes</h1>
<%= link_to 'New Quote', new_quote_path, data: { turbo_frame: dom_id(Quote.new) } %><br>
<%= turbo_frame_tag Quote.new %>
<%= turbo_frame_tag 'quotes' do %>
<%= render #quotes %>
<% end %>
View (new.html.erb)
<h1>New Quote</h1>
<%= turbo_frame_tag #quote do %>
<%= render "form" %>
<% end %>
create.turbo_stream.erb
<%= turbo_stream.prepend 'quotes', #quote %>
<%= turbo_stream.update Quote.new, '' %>
I used this tutorial for making polymorphic comments
https://gorails.com/episodes/comments-with-polymorphic-associations
It works fine but when I set remote true to my comments form I got 505 error(the new comment is not appended to the list) when trying to add a new comment.
But when I reload the page the new comment appears in the list.
What can be wrong here?
I got this files in views/comments folder:
create.js
<% unless #comment.errors.any? %>
$("ul.comments").append('<%= j render "comments/comment" %>')
$("#new_comment")[0].reset();
<% end %>
_form.html.erb
<%= simple_form_for([commentable, Comment.new], remote: true) do |f| %>
<%= f.input :body, label: false %>
<%= f.button :submit, "Submit" %>
<% end %>
comments_controller.rb
def create
#comment = #commentable.comments.new(comment_params)
#comment.user = current_user
#comment.save
respond_to do |format|
format.html { redirect_to #commentable, notice: "Your comment was successfully added."}
format.js
end
end
_comment.html.erb
<li class="comment">
<b><%= comment.user.try(:username) %>:</b>
<%= comment.body%>
</li>
console
UP
I got this routes for post
resources :posts do
resources :comments, module: :posts
end
+
controllers/posts/comments_controller
class Posts::CommentsController < CommentsController
before_action :set_commentable
private
def set_commentable
#commentable = Post.friendly.find(params[:post_id])
end
end
The folder structure looks almost the same as here
https://github.com/excid3/gorails-episode-36/tree/master/app/controllers
the response tab shows this
undefined local variable or method `comment' for #<#<Class:0x007f993d3c5450>:0x007f99450a6190>
Trace of template inclusion: app/views/comments/create.js.erb
and when I replace
<%= j render #comment %> with some text it appends to the list on submit
ok the problem is with _comment.html erb
updated create.js with instance variable for comment and it works now.
<% unless #comment.errors.any? %>
$("ul.comments").append('<%= j render partial: "comments/comment", locals:{comment: #comment} %>')
$("#new_comment")[0].reset();
<% end %>
I am able to update the like and unlike button via ajax, but I am not able to update the like count.
Post has_many likes
likes_controller.rb
def create
#like = Like.new(:post_id => params[:post_to_be_liked])
if #like.save
respond_to do |format|
format.html {redirect_to :back, notice: "Liked!"}
format.js
end
end
end
view.html.erb
<% #post = user.posts.first %>
<div id="send_like_for_<%= #post.id %>">
<% if #post.is_liked?(#post, current_user)%>
<%= render 'unlike'%>
<%else%>
<%= render 'like'%>
<%end%>
</div>
<div id="liked_<%= #post.id %>" %>
<%= render 'liked_users'%>
</div>
create.js.erb
$("#send_like_for_<%= params[:post_to_be_liked]%>").html("<%= escape_javascript(render('users/unlike')) %>")
$("#liked_<%= params[:post_to_be_liked]%>").html("<%= escape_javascript(render('users/liked_users')) %>")
_like.html.erb
<%= link_to "LIKE", likes_path(:post_to_be_liked => #post.id), remote: true, :method=>:post %>
_unlike.html.erb
<span> UNLIKE </span>
_liked_users.html.erb
<%= "#{#post.likes.length} like this" %>
The like/unlike functionality works just fine and when someone likes the post the button changes to Unlike. But the like count doesn't increase.
But why are you doing this in your view?
<% #post = user.posts.first %>
It will update only your first post always. I can't understand.
Try with this:
_liked_users.html.erb
<%= #updated_post = Post.where(id: #post.id) %>
<%= "#{#updated_post.likes.length} like this" %>
or
<%= #post.reload %>
<%= "#{#post.likes.length} like this" %>
Edit (Try to build your like this):
def create
#post = Post.where(id: params[:post_to_be_liked])
#like = #post.likes.build(:post_id => #post.id)
if #like.save
respond_to do |format|
format.html {redirect_to :back, notice: "Liked!"}
format.js
end
end
end
I think you should try to do this
#post = user.posts.first
after save in your controller and remove <% #post = user.posts.first %> from erb file and if it is not possible then initialize #post in your controller#create
#post = Post.find(params[:post_to_be_liked])
My update.html.erb:
<% #uploads.each do |upload| %>
<p><%= upload.name %></p>
<p class="grey">
<%= best_in_place upload, :place, type: :select, collection: [ ["Home", "Home"],["Sauna", "Sauna"]]%>
</p>
<%end%>
controller:
def show
#uploads = Upload.all
end
def update
#uploads = Upload.all
#upload = Upload.find(params[:id])
respond_to do |format|
if #upload.update_attributes(params[:upload])
format.html { redirect_to #upload, notice: 'Upload was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #upload.errors, status: :unprocessable_entity }
end
end
end
The problem is that I get the error: undefined methodeach' for nil:NilClass` , meaning that my controllers do not pass my object to the variable #uploads. Why do not the do that and how can I fix it? Thanks in advance.
ps. I could write at the top of my view something like this:
<% #uploads=Uploads.all%>
But that is not the best idea.
Thanks in advance
<% #uploads.each do |upload| %>
<%end if #uploads.present? %>
IF your routes are RESTful routes, the update method is a HTTP PUT method and it shouldn't have a template. What you are looking for is a edit action:
def edit
#uploads = Upload.all
end
#katja: Referring to your comment.
update is a HTTP PUT request, you cant get a record in that but edit is a get request you can get all records in edit action.
You can add a before_filter callback to your edit action.
before_filter :get_all_uploads, only: [:edit]
def get_all_uploads
#uploads = Upload.all
end
And in your edit.html.erb you can do
<% #uploads.each do |upload| %>
<p><%= upload.name %></p>
<p class="grey">
<%= best_in_place upload, :place, type: :select, collection: [ ["Home", "Home"],["Sauna", "Sauna"]]%>
</p>
<% end %>
Hi I am currently making an app with users, albums, and photos. I managed to make the AJAX work for the create action when I upload pics, but I can't get AJAX to work for the delete. Instead, it redirects me to an empty show page for the pic. Can anyone give me some guidance?
photos controller:
def destroy
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:album_id])
#photo = #album.photos.find(params[:id])
# #photo.destroy
flash[:success] = "Photo successfully deleted."
respond_to do |format|
if #photo.destroy
format.js
# format.json { render json: #photo, status: :created, location: #photo}
# redirect_to user_album_path(#user, #album)
end
end
end
destroy.js.erb (I'm supposed to have this right?)
$('.destroypicswrapper').remove(".<%= #photo.avatar.url %>");
_photodestroy.html.erb partial:
<div class="picthumb <%= photo.avatar.url %>">
<%= link_to image_tag(photo.avatar.url ? photo.avatar.url(:small) : #album.name), root_url %>
<br>
<%= link_to "Delete", user_album_photo_path(#user, #album, photo), :remote => true, method: :delete, data: { confirm: "Are you sure? "} %>
</div>
and finally the albums/edit.html.erb page where the delete is initially happening:
<% provide(:title, "Edit album") %>
<%= render 'form' %>
<div class="destroypicswrapper">
<% if #album.photos.any? %>
<%= render :partial => 'photodestroy', :collection => #album.photos, :as => :photo %>
<% end %>
</div>
I don't think you want to render the full url of an image as a class of a div. Also, your Jquery is wrong. Try something like this:
destroy.js.erb
$('.destroypicswrapper > #photo_<%= #photo.id %>').remove();
Adjust your _photodestroy.html.erb to:
<div class="picthumb" id="photo_<%= photo.id %>">