I am currently working on a simple website where people can list postings. Most of the code is based on Michael Hartl's tutorial.
I want users to have the ability to click on a link that displays the listing individually.
currently, the listings' of each user are found under
http://localhost:3000/users/id
Every listing has it's own id
Here are my routes
Rails.application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :listings
root 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via:'delete'
match '/help', to: 'static_pages#help', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/new', to: 'listings#new', via: 'get'
Here is my listing_controller.rb
class ListingsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy, :edit]
before_action :correct_user, only: :destroy
def create
#listing = current_user.listings.build(listing_params)
if #listing.save
flash[:success] = "Job Post created"
redirect_to current_user
else
render 'listings/new'
end
end
def edit
end
def show
#listing = Listing.find(params[:id])
end
def new
#listing = Listing.new
#listings = Listing.paginate(page: params[:page])
end
def destroy
#listing.destroy
redirect_to current_user
end
private
def listing_params
params.require(:listing).permit(:description, :location, :title)
end
def correct_user
#listing = current_user.listings.find_by(id: params[:id])
redirect_to current_user if #listing.nil?
end
def current_listing
#listings = listing.find(params[:id])
end
end
I also created a show page for each listing under listings the listings folder.
The show page itself works.
Here is the show.html.erb for the listing
<div class="show_listing">
<div class="col-md-6">
<div class="col-md-6">
<h3><%= #listing.title %></h3>
<h3><%= #listing.location %></h3>
<p><%= #listing.description %></p><br>
<div class="center">
<%= link_to "Apply Now", '#', class: "btn btn-info", data: {no_turbolink: true} %>
</div>
</div>
</div>
</div>
<div class="show_link_position">
<% if current_user == #listing.user %>
<%= link_to 'Edit', '#', class: "btn btn-link" %> |
<% end %>
<%= link_to 'Back', current_user, class: "btn btn-link" %>
</div>
Now I would like to have a link on the user page (under each listing) that would link to each post individually.
I'm looking for something like this
how to display a link to individual microposts? (ruby on rails 3)
Thank you
Let me know if you need more information
To create a link from a page where you have the collection of listings as #listings, you might have something like this...
<ol class="listings">
<% #listings.each do |listing| %>
<div class="listing">
<h2><%= listing.title</h2>
<h3><%= listing.location</h3>
<p><%= listing.description</p>
<%= link_to "Show", listing, class: "btn btn-link" %>
</div>
<% end %>
</ol>
Here is what I did to get it to work (with the help of the following stackoverflow post how to display a link to individual microposts? (ruby on rails 3))
Routes rb.
match '/users/:id/:id', to 'listings#show', via: :get, as: :user_listing
users view file
add the link
<li><%= link_to "Show", user_listing_path(id: #user.id, id: listing.id) %></li>
Changed my listing_controller file
def show
#user = User.find_by_id(params[:id])
#listing = Listing.find_by_id(params[:id])
end
Related
I'm trying to display all albums in the albums#index page but I'm getting an error in my Albums controller "cannot find album without ID". I understand the issue is that there are no params, but I've used the find method with params[:id] a bunch of times in my app and haven't had this issue thus far.
For reference, Albums have many Reviews and have many Users through Reviews.
Users have many Reviews and have many Albums through Reviews.
I haven't built out my Reviews controller yet so that's unrelated.
Here is the error:
ActiveRecord::RecordNotFound in AlbumsController#index
Couldn't find Album without an ID
Extracted source (around line #40):
38
39
40
41
42
43
def set_album
#album = Album.find(params[:id])
end
def album_params
Rails.root: /Users/melc/review_project
Application Trace | Framework Trace | Full Trace
app/controllers/albums_controller.rb:40:in `set_album'
Request
Parameters:
None
Here is my Albums controller:
class AlbumsController < ApplicationController
before_action :set_album, only: [:index, :show, :edit, :update]
def index
#albums = Album.all
#current_user
end
def show
end
def new
#album = Album.new
end
def create
#album = Album.new(album_params)
if #album.save
redirect_to album_path(#album)
else
render :new
end
end
def edit
end
def update
if #album.update(album_params)
redirect_to album_path(#album), notice: "Your album has been updated."
else
render 'edit'
end
end
private
def set_album
#album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:artist, :title, :avatar)
end
end
Here is my albums#index view:
<h2>All Albums</h2>
<br>
<br>
<% if #album.avatar.attached? %>
<image src="<%=(url_for(#album.avatar))%>%" style="width:350px;height:350px;">
<% end %>
<br>
<%= #album.artist %> -
<%= #album.title %>
<br>
<%= link_to "Edit Album", edit_album_path %><br><br>
<%= link_to "Upload a New Album", new_album_path %>
Here is the routes.rb file:
Rails.application.routes.draw do
get '/signup' => 'users#new', as: 'signup'
post '/signup' => 'users#create'
get '/signin' => 'sessions#new'
post '/signin' => 'sessions#create'
get '/signout' => 'sessions#destroy'
resources :albums do
resources :reviews
end
resources :users
root to: "albums#index"
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
you need to change a couple things here:
on AlbumsController, you need to remove index from actions that "preload" an album
before_action :set_album, only: [:show, :edit, :update]
You need to pass the album object to the route in the view:
<%= link_to "Edit Album", edit_album_path(#album) %><br><br>
hope that helps
EDIT: about the avatar issue, looks like you're displaying the albums in the index, but you aren't iterating through them, something like:
<h2>All Albums</h2>
<% #albums.each do |album| %>
<br>
<br>
<% if album.avatar&.attached? %>
<image src="<%=(url_for(album.avatar))%>%" style="width:350px; height:350px;">
<% end %>
<br>
<%= album.artist %> - <%= album.title %>
<%= link_to "Edit Album", edit_album_path(album) %><br><br>
<br>
<% end %>
<%= link_to "Upload a New Album", new_album_path %>`
I have created a ToDoList based off Hartl's tutorial, and following a video and worded tutorial to add a tagging system. I have followed till Section 10, where they asked me to modify my new.html.erb file to the code as shown on the source. To improvise for structural differences in code, I would edit some other files, like in this case, my micropost_form partial instead. Occasionally, I alternated between the code in the video and code in the worded tutorial because some of them would produce error messages or would not produce the required functionality. Here are the files that I think are involved in this question.
_micropost_form.html.erb(The filling up form that would be displayed on the user's home page)
<%= simple_form_for #micropost do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content, placeholder: "Add new task..." %>
</div>
<div class="field">
<%= f.label :tag_list, "Tags (separated by commas)" %><br />
<%= f.text_field :tag_list %>
</div>
<%= f.submit "Add Task", class: "btn btn-primary" %>
<% end %>
micropost.html.erb(for showing the individual micro posts)
<li id="micropost-<%= micropost.id %>">
<%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
<span class="user"><%= link_to micropost.user.name, user_path(micropost.user) %></span>
<span class="content"><%= micropost.content %></span>
<p><small>Tags: <%= raw micropost.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %></small</p>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
<% if current_user?(micropost.user) %>
<%= link_to "Done", micropost_path(micropost), method: :delete, data: { confirm: "Keep up the good work!" } %>
<% end %>
</span>
</li>
routes.rb
Rails.application.routes.draw do
resources :users
resources :microposts
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/users/admin', to: 'users#admin'
get 'tags/:tag', to: 'microposts#index', as: :tag
root 'static_pages#home'
end
micropost_controller
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
params[:tag] ? #microposts = Micropost.tagged_with(params[:tag]) : #microposts = Micropost.all
end
def show
#micropost = Micropost.find(params[:id])
end
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
flash[:success] = "You have deleted a task!"
redirect_to request.referrer || root_url
end
private
def micropost_params
params.require(:micropost).permit(:content, :tag_list, :tag,
{tag_ids: [] }, :tag_ids)
end
def correct_user
#micropost = current_user.microposts.find_by(id: params[:id])
redirect_to root_url if #micropost.nil?
end
end
Micropost model
class Micropost < ApplicationRecord
belongs_to :user
has_many :taggings
has_many :tags, through: :taggings
default_scope -> { order(created_at: :desc) }
validates :user_id, presence: true
validates :content, presence: true, length: {maximum: 140 }
attr_accessor :tag_list
def self.tagged_with(name)
Tag.find_by!(name: name).microposts
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
attr_accessor :name
has_many :taggings
has_many :microposts, through: :taggings
end
static_pages controller
class StaticPagesController < ApplicationController
def home
if logged_in?
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
def help
end
def about
end
def contact
end
end
feed.html.erb
<% if #feed_items.any? %>
<ol class="microposts">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
I got the following error
ActionController::UrlGenerationError in StaticPages#home
No route matches {:action=>"index", :controller=>"microposts", :tag=>nil}, missing required keys: [:tag]
app/views/microposts/_micropost.html.erb:5:in `block in _app_views_microposts__micropost_html_erb___3891111682689684005_70324923859580'
app/views/microposts/_micropost.html.erb:5:in `map'
app/views/microposts/_micropost.html.erb:5:in `_app_views_microposts__micropost_html_erb___3891111682689684005_70324923859580'
app/views/shared/_feed.html.erb:3:in `_app_views_shared__feed_html_erb__3168328449514417483_70324923896060'
app/views/static_pages/home.html.erb:13:in `_app_views_static_pages_home_html_erb__3511776991923566869_70324898321240'
Can anyone suggest what might be wrong here? Please let me know if more information is needed.
Update: I have implemented some of the changes provided by the answer below, but still has not understood why :tag is not detected, and why the code in red is actually highlighted.
ActionController::UrlGenerationError in StaticPages#home
No route matches {:action=>"index", :controller=>"microposts", :tag=>nil}, missing required keys: [:tag]
The problem is you don't have an index route for your microposts.
Rails.application.routes.draw do
root 'static_pages#home'
get '/readme', to: 'static_pages#readme'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/users/admin', to: 'users#admin'
resources :users
resources :microposts, only: [:create, :destroy] #Here's the problem
get 'tags/:tag', to: 'microposts#index', as: :tag
end
change to:
resources :microposts, only: [:index, :create, :destroy]
EDIT:
Another problem is
if logged_in?
#micropost = current_user.microposts.build #this just returns a new 1
#feed_items = current_user.feed.paginate(page: params[:page])
end
You probably want something like:
if logged_in?
#microposts = current_user.microposts
#feed_items = Micropost.all.paginate(page: params[:page])
end
This will give you all the user's microposts. Then you iterate through them in your views.
I actually found the cause of the problem to be quite simple. After running rails console, it seems like my db:seed wasn't even raked properly, causing my tags to have nil names and causing me to be unable to find the route. Looking further into Rails console is adding nil instead of values to solve my seed adding problem, I realised I have added attr_accessor, forgetting that normal attributes should be added via the command line into the Migration instead of writing into the Model directly. Removing it according to the post updates my database and the code works.
I want to use three models in one controller
if click tag '삭제', I want to execute free_destroy action in management controller.
When I click the link, this error page occurs:
ActiveRecord::RecordNotFound in ManagementsController#free_destroy
and Couldn't find Management with id=1
How can i fix it?
Why does this error occur?
Please answer for me.
controller
class ManagementsController < ApplicationController
load_and_authorize_resource param_method::params_management
def index
#users = User.all
#freemanages = Freemanagement.all
end
def freepost_delete
#freemanage = Freemanagement.new(params.require(:modal).permit(:content, :title_id))
#freemanage.save()
redirect_to :back
end
def secret_delete
# #secretmanage = Secretmanagement.new(params.require(:modal).permit(:content, :title_id))
# #secretmanage.save()
# redirect_to :back
end
def show
freemanage = Freemanagement.find(params[:id])
redirect_to freemanagements_path(freemanage), method: :delete
end
def free_destroy
freemanage = Freemanagement.find(params[:id])
freemanage.destroy()
redirect_to freepost_path(freemanage.title_id), method: :delete
end
def refuse_freepost
freepost = Freepost.find(params[:remodal][:title_id])
freemanages = Freemanagement.all
freemanages.each do |freemanage|
if (freemanage.title_id.to_i != freepost.id)
next
else
freemanage.destroy()
end
end
redirect_to :back
end
def refuse_secretpost
end
end
index.html
<head>
</head>
<body>
<header>
<!-- 공지사항 작성 글 -->
<%= link_to '익명겟', secretposts_path %>
<%= link_to '자유겟', freeposts_path %>
<%= current_user.last_name + current_user.first_name %>
</header>
<section>
<% #users.each do |user| %>
<%= user.uid %>
<%= user.first_name %>
<%= user.last_name %>
<%= user.roles_name%>
<% end %>
</section>
<section>
<% #freemanages.each do |freemanage| %>
<%= link_to '게시글보기', freepost_path(freemanage.title_id) %>
<%= freemanage.content %>
<a href='/freemanagements/<%= freemanage.id %>/delete'>삭제</a>
<br />
<% end %>
</section>
<section>
<!-- 익명게시판 관련 게시글 섹션 -->
</section>
<script>
</script>
</body>
routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'homes#index'
resources :freeposts do
resources :free_comments
end
resources :secretposts do
resources :secret_comments
end
resources :free_comments
resources :secret_comments
get '/managements' => 'managements#index'
get '/freemanagements/:id' => 'managements#show'
post '/freemanagements' => 'managements#freepost_delete'
get '/freemanagements/:id/delete' => 'managements#free_destroy'
post '/freemanagements/refuse' => 'managements#refuse_freepost'
post '/secretmanagements' => 'managements#secretpost_delete'
get 'login', to: redirect('/auth/google_oauth2'), as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
# get 'home', to: 'home#show'
# get 'me', to: 'me#show', as: 'me'
end
I'm using the mailboxer gem to build a messaging system between users for my rails application. For some reason, I'm getting this error:
(undefined method `receipts_for' for nil:NilClass)
Maybe it's because I should define 'receipts_for' somewhere in my controller or in the mailboxer.rb? I tried a few things.. but unfortunately none of them were successful.
This is my routes.rb:
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
get 'search/index'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users do
member do
get :following, :followers
end
end
resources :conversations do
resources :messages
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :relationships, only: [:create, :destroy]
resources :searches
end
This is my conversations controller:
class ConversationsController < ApplicationController
def show
#conversation = current_user.mailbox.conversation.find(params[:id])
end
def new
#recipients = User.find(params[:user_id])
end
def create
recipient = User.find(params[:user_id])
receipt = current_user.send_message(recipient, params[:body])
redirect_to conversation_path(receipt.conversation)
end
end
This is my messages_controller:
class MessagesController < ApplicationController
before_action :set_conversation
def create
receipt = current_user.send_message(#conversation, body)
redirect_to receipt.conversation
end
private
def set_conversation
#conversation = current_user.mailbox.conversations.find(params[:conversation_id])
end
end
The messaging system I'm building precisely, is a messaging system where the 'current_user' can go to the profile page of any user on the application and message him/her via the profile page. So this means that I'm rendering show.html.erb of the conversation model inside the show.html.erb of my users model. Here is the code of both views:
show.html.erb - Users Model:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
<section class="stats">
<%= render 'shared/stats' %>
</section>
<h6>
<%= #user.gender %>
</h6>
<%= render "conversations/conversation" %>
</aside>
<div class="col-md-8">
<%= render 'follow_form' if logged_in? %>
<% if #user.microposts.any? %>
<h3>Microposts (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
_conversation.html.erb - show view of the conversations model.
<% #conversation.receipts_for(current_user).each do |receipt| %>
<div>
<%= receipt.message.body %>
</div>
<% end %>
<%= form_tag conversation_messages_path(#conversation), method: post do %>
<div>
<%= text_area_tag :body %>
</div>
<%= submit_tag %>
<% end %>
So how exactly can I define the 'receipts_for' method for my mailboxer? Or is something else wrong with my code?
Any help would be much appreciated!
Thanks!
I’ll piggy-back on what #mu is too short said. It’s important to pay attention to the whole error message. “undefined method receipts_for for nil:NilClass” is telling you that the receiver of the receipts_for method is nil. #conversation.receipts_for(current_user) looks to be the only place where receipts_for is used, so I would start debugging by making sure #conversation is assigned the value of an existing ActiveRecord-backed conversation object.
There seems to be too a lot going on, so I don't know how to offer you a quick fix. The value assignment in your ConversationsController#show method, #conversation= current_user.mailbox.conversation.find(params[:id]) looks cumbersome. That suggests to me that you're looking for a conversation based on a mailbox belonging to the current_user, which might be what you want (in which case, you need to have the appropriate associations defined in your models).
However, since the chain ends with conversation.find(params[:id]), I'm guessing that current_user.mailbox is not needed. Alternatively, if your params don't actually have a conversation id, then maybe that's what you need to focus on.
The good news is you can probably figure out how to define #conversation if you stick byebug (or binding.pry, depending on what you have installed) at the top of your show method and in your view partial:
# In the controller:
def show
binding.pry
#conversation = current_user.mailbox.conversation.find(params[:id])
end
# in the view
<% binding.pry %>
I have problem with a nested delete method for a link_to helper.
Here are my routes:
resources :restaurants, only: [:new, :show, :edit, :index,:create] do
resources :reservations, only: [:new, :show, :edit, :index, :create]
resources :reviews
end
Here is my review controllers action:
def destroy
#review = Review.find(params[:id])
#review.destroy
end
and my code on user#show:
<div class="panel-body">
<h1> <%= pluralize(#user.reviews.count ,'review') %> from <%= #user.name %> </h1>
<% #user.reviews.order(created_at: :desc).each do |review| %>
<ul>
<li><em>Review for restaurant: </em><%= review.restaurant.name %></li>
<em>Review comment: </em> <%= review.comment %></br>
<%= link_to 'edit comment', edit_restaurant_review_path(review.restaurant_id, review.id) %>
<%= link_to 'delete comment', restaurant_review_path( #user, review.id ) , method: :delete, data:{confirm:"are you sure you want to delete this review"} %>
</ul>
<% end %>
</div>
Here is my route:
restaurant_reviews GET /restaurants/:restaurant_id/reviews(.:format) reviews#index
POST /restaurants/:restaurant_id/reviews(.:format) reviews#create
new_restaurant_review GET /restaurants/:restaurant_id/reviews/new(.:format) reviews#new
edit_restaurant_review GET /restaurants/:restaurant_id/reviews/:id/edit(.:format) reviews#edit
restaurant_review GET /restaurants/:restaurant_id/reviews/:id(.:format) reviews#show
PATCH /restaurants/:restaurant_id/reviews/:id(.:format) reviews#update
PUT /restaurants/:restaurant_id/reviews/:id(.:format) reviews#update
DELETE /restaurants/:restaurant_id/reviews/:id(.:format) reviews#destroy
I can't seem to delete my reviews. Am I passing in the wrong variables?
to 'restaurant_review_path'? My route seems to be right. as my edit link_to helper is working.
restaurant_review_path( #user, review.id ) is wrong. You're passing #user as the restaurant argument, which is going to produce a link with the wrong ID.
You should be giving it a restaurant (or restaurant ID) and a review, not a user and a review id, just like you're doing on the previous line with the edit link.
restaurant_review_path(review.restaurant_id, review.id)