I'm trying to show the avatar of each user who has commented in a topic. I pretty much have a Topic Model and a Comment Model. In my index page i have a list of all the topics created and a list of avatar of the user who commented but it only gets the list of the first topic and the images get repeated.
This is what i have in my index but I end up getting the avatar of each comment with repeated images.
<tbody>
<% #topics.each do |topic| %>
<th class="topic"> <%= link_to topic.title, topic %> </th>
<th class="category"><%= topic.category.title %></th>
<th class="users"><%= image_tag topic.user.avatar.url(:thumb)%></th>
<th class="replies"><%= topic.comments.count %> </th>
<th class="replies"></th>
<th class="activities"></th>
<% #comment.each do |comment| %>
<%= image_tag comment.user.avatar.url(:thumb) %>
<% end %>
<% end %>
</tbody>
My comments controller
class CommentsController < ApplicationController
def index
#topics = Topic.all
#comments = Comment.includes(:user)
end
def create
#comment = #commentable.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.save
redirect_to #commentable
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
You are displaying the user of only one comment.
<% #comment.each do |comment| %>
You probably need to get all comments of the topic instead. See below.
<% topic.comments.each do |comment| %>
To avoid N+1 issue, you can eager load the comments too
def index
#topics = Topic.includes(:comments => :user)
end
To display unique users, you can use Array#uniq with a block.
Assuming comments table has user_id, as foreign key,
<% topic.comments.uniq(&:user_id).each do |comment| %>
Related
I searched for the answer, but I couldn't find the same problem.
Basically - I'm building a simple CMS, and I'm building a controller with a view, but it isn't working. I can press the submit button, but the form gives no response, it doesn't even output any errors.
I also noticed it changes the url from /pages/new to /pages, but it stays on the form.
Page Controller:
def index
#pages = Page.sorted
end
def show
#page = Page.find(params[:id])
end
def new
#page = Page.new
end
def create
#page = Page.new(page_params)
if #page.save
flash[:notice] = "Page created succesfully."
redirect_to pages_path
else
render('new')
end
end
def edit
#page = Page.find(params[:id])
end
def update
#page = Page.find(params[:id])
if #page.update_attributes(page_params)
flash[:notice] = "Subject updated succesfully."
redirect_to page_path(#page)
render('edit')
end
end
def delete
#page = Page.find(params[:id])
end
def destroy
#page = Page.find(params[:id])
#page.destroy
flash[:notice] = "Page '#{#page.name}' destoyed succesfully."
redirect_to(pages_path)
end
private
def page_params
params.require(:page).permit(:subject_id, :name, :position, :visible, :permalink)
end
new.html.erb:
<%= link_to("<< Back To List", pages_path, :class => 'back-link') %>
<div class = "pages new">
<h2>Create Page</h2>
<%= form_for(#page, :url => pages_path, :method => 'post') do |f| %>
<table summary = "Page form fields">
<tr>
<th> Name: </th>
<td><%= f.text_field(:name) %></td>
</tr>
<tr>
<th> Subject ID: </th>
<td><%= f.text_field(:subject_id) %></td>
</tr>
<tr>
<th> Permalink: </th>
<td><%= f.text_field(:permalink) %></td>
</tr>
<tr>
<th>Position: </th>
<td><%= f.text_field(:position) %></td>
</tr>
<tr>
<th>Visible: </th>
<td><%= f.text_field(:visible) %></td>
</tr>
</table>
<div class="form-buttons">
<%= f.submit("Create Page") %>
</div>
<% end %>
</div>
EDIT:
tried changing the form code to <%= form_for(#page) do |f| %>, but I still have the same problem
I added the #page.save! part of the code and it gave me a error which showed me errors which are deeper down in my code! At least I fixed this problem. Thank you very much.
It seems that the information from your form is not valid, try using save! instead of save in your create action:
def create
#page = Page.new(page_params)
if #page.save!
flash[:notice] = "Page created succesfully."
redirect_to pages_path
else
render('new')
end
end
That will show the error on your logs.
Trying out ruby, i just asked a question but here's another, getting undefined method `each' for # and i tried a lot of stuff
<h1>This is the index page</h1>
<p>I need to get the new action running!</p>
<%= link_to 'My Blog', controller: 'posts' %>
</br>
<%= link_to 'New post', new_post_path %>
<h1>Listing posts</h1>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #posts.each do |post| %> ///<----ERROR HERE!
<tr>
<td><%= posts.title %></td>
<td><%= posts.description %></td>
<td><%= link_to 'Show', posts_path(posts) %></td>
<td><%= link_to 'Edit', edit_posts_path(posts) %></td>
</tr>
<% end %>
</table>
This is my controller:
class PostsController < ApplicationController
def index
#posts = Post.new
end
def edit
#posts = Post.find(params[:id])
end
def update
#posts = Post.find(params[:id])
if #posts.update(posts_params)
redirect_to #posts
else
render 'edit'
end
end
def new
#posts = Post.new
end
def create
#posts = Post.new(posts_params)
if #posts.save
redirect_to #post
else
render 'new'
end
end
def show
#posts = Post.find(params[:id])
end
private
def posts_params
params.require(:posts).permit(:title, :description)
end
end
I'm pretty sure i changed eveything to be matching like #posts from #post, i would appreciate if someone could help me again, i've tried looking for an answer but not getting luck, thank you
In your controller under the index do:
def index
#posts = Post.all
end
Then in your view after your each do refer to the variable as post, not posts.
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.description %></td>
<td><%= link_to 'Show', post_path(post) %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
Modify the index method in your controller to the following:
def index
#posts = Post.all
end
Post.new returns a single (empty) objet, the each method expects an enumerable (array, hash, collection,...), hence the error.
Your #posts instance variable is pointing to a new post record instead of a collection of posts. You need an array to iterate over instead of a single post.
If you want to call .each on an object, that object has to be made up of a collection of data (even if the "collection" has one element).
You're calling Post.new - meaning the .each method is going to return an exception that it cannot cycle through the expected collection.
You need to do the following:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = Post.all
end
end
This should get your code working.
so i have installed best in place gem in a rails 4 environment and initialised it correctly. (i can click on the name field and the box becomes editable).
I've this code in my admin_namespaced user controller
class Admin::UsersController < Admin::BaseController
def index
#users = User.all
# #columns = User.column_names
end
def show
#user = User.find(params[:id])
end
def update
#user = User.find params[:id]
respond_to do |format|
if #user.update_attributes(user_params)
format.html { redirect_to(user, :notice => 'User was successfully updated.') }
format.json { respond_with_bip(#user) }
else
format.html { render :action => "index" }
format.json { respond_with_bip(#user) }
end
end
end
private
def user_params
params.require(:user).permit(:name,:email,:password,:password_confirmation)
end
end
and basically i want to use it in conjuction with rails datatables gem that i successfully setup, to inline-edit corresponding fields.
this is the html.erb code in my user index view
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= link_to "Back", admin_path %>
<table class="display responsive no-wrap text-center" id="usertableadmin">
<thead>
<tr>
<th>id</th>
<th>Username</th>
<th>Email</th>
<th>Activated?</th>
<th>Admin?</th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= best_in_place user, :name%></td>
<td><%= user.email %></td>
<td><%= user.activated %></td>
<td><%= user.admin %></td>
</tr>
<% end %>
</tbody>
</table>
here is what the html code looks like on the tag that has the best_in_place initialization.
<span data-bip-type="input" data-bip-attribute="name" data-bip-object="user" data-bip-original-content="Example User" data-bip-url="/users/1" data-bip-value="Example User" class="best_in_place" id="best_in_place_user_1_name">Example User</span>
I dont know for sure but for some reason the fields do not get updated. When i click to change the name it gets reverted to the previous one.
I dont know if its because i have a namespace, admin/users or its because its the index action and not the show action.
any insight is welcome.
I've found the solution,
it seems the error was the update url it was wrong because of the namespace.
What i had to do, was to include url parameter like below
<td><%= best_in_place user, :name, url: "users/#{user.id}" %></td>
Newbie to rails, I think i might be overlooking something very simple here, but I am displaying a table twice in a partial, not sure if it's to do with my associations.
Here is the Properties controller:
class PropertiesController < ApplicationController
before_filter
def index
#property= Property.all
end
def new
#property = current_user.property.build if signed_in?
end
def show
#property = current_user.property.paginate( params[:page])
end
Here is the Users Controllers:
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#users = User.all
end
def show
#user = User.find(params[:id])
#property = #user.property.paginate(page: params[:page])
end
Here are the associations in the models:
user model:
class User < ActiveRecord::Base
has_many :property, dependent: :destroy
property:
class Property < ActiveRecord::Base
attr_accessible :address, :name
belongs_to :user
Here is the _property.html.erb partial
<li>
<table>
<tr>
<th>Name</th>
<th>address</th>
</tr>
<% #user.property.each do |property| %>
<tr>
<td><%= property.name %></td>
<td><%= property.address %></td>
</tr>
<% end %>
</table>
</li>
Here is the show.html.erb
<div class="row">
<aside class="span4">
<section>
<h1>
My Properties
</h1>
</section>
</aside>
<div class="span8">
<% if #user.property.any? %>
<h3>Properties (<%= #user.property.count %>)</h3>
<ol>
<%= render #property %>
</ol>
<%= will_paginate #property %>
<% end %>
</div>
</div>
This is what is rendered in the browser. http://i.imgur.com/SlilDo3.png
Let me know if there is anything else will be of help with this question. All responses appreciated.
Where you do #property = Property.all you are setting up a collection of instances of the Property class... there's clearly more than on in this collection.
When you use
render #property
it will render the _property template for every item in the collection called #property
Even if, inside the _property template you then use user.property.each - then that means that you're effectively saying:
for each property in #property, render the template _property... and
each time you do that, render a new table that does a table row for
each property in user.property.
if you want only one table, and only each row to be rendered per individual "property" in the list of properties that is called #property then you need to pull the table outside of the render.
eg:
<h3>Properties (<%= #user.property.count %>)</h3>
<table>
<tr>
<th>Name</th>
<th>address</th>
</tr>
<%= render #property %>
</table>
and _property:
<tr>
<td><%= property.name %></td>
<td><%= property.address %></td>
</tr>
I have 2 classes: Posts and Comments, where posts has_many :comments and comments belongs_to post.
Each of my posts has a show page with a list of comments and I would like to paginate the comments. With the current code I have, I'm showing a list of all the comments on all the pages. So, If i have 10 comments and I want to have 2 on each page, I get 5 pages with the original 10 comments on it. Could someone shed some light?
My Code:
Posts controller:
def show
#post = Post.find(params[:id])
#comments = #post.comments.page(params[:page]).per(3)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
"Show" views:
<%= paginate #comments %>
<% #post.comments.each_with_index do |comments, index| %>
<tr>
<td><%= index+1 %></td>
<td><%= comment.date %></td>
<td><%= comment.text %></td>
</tr>
<% end %>
</table>
You need to use the paginated object in the view, not get them fresh from the database:
<% #comments.each_with_index do |comments, index| %>
<tr>
<td><%= index+1 %></td>
<td><%= comment.date %></td>
<td><%= comment.text %></td>
</tr>
<% end %>
This gets them fresh, unpaginated:
#post.comments