How can we list out the user's name who submitted the habit: <%= link_to #habit.user.name, #user %>, but upon clicking on it the user is redirected back to the show page: http://0.0.0.0:3000/habits/1 instead of being redirected to the user's profile page: http://0.0.0.0:3000/users/1?
habits_controller
def show
#notable = #habit
#notes = #notable.notes
#note = Note.new
#commentable = #habit
#comments = #commentable.comments
#comment = Comment.new
#correct_user = current_user.habits.find_by(id: params[:id])
end
routes.rb
resources :users do
resources :habits
end
resources :habits do
resources :notes
resources :notifications
resources :comments do
resources :likes
end
member do
post :like
post :notifications
end
resources :levels do
# we'll use this route to increment and decrement the missed days
resources :days_missed, only: [:create, :destroy]
end
end
When you pass #user as the second parameter of the link_to method call, Rails is inferring the user_path route. Instead of #user, you should be able to pass #habit and see the appropriate behavior.
If the implicit path argument doesn't work, you could more specifically pass habit_path(#habit.id)
Have you tried to change the link url to be more specific?
I.e. <%= link_to #habit.user.name, user_path(#habit.user) %>
I guess your #user instance is not defined correctly. What you defined as #user is actually habit instance.
Related
I need to edit the card element from the card index page, on this page I have only one parameter - the card ID. The decrease in the number of parameters was due to rewriting the route for the index page only.
I am new to Ruby and do not quite understand how I can find these parameter(board_id, column_id). Controllers with the function of updating the card are already there. How do I find these options correctly?
I have this routes:
get 'cards' => 'cards#index', as: :cards
resources :boards do
resources :columns, except: [:index, :show, :edit] do
resources :cards, except: [:index, :show]
end
end
end
So to edit the card element I need :board_id, :column_id, cards/:id:
board_column_card_path PATCH /boards/:board_id/columns/:column_id/cards/:id(.:format) cards#update
My cards_controller:
class CardsController < ApplicationController
def new; end
def index
#cards = Card.all.order(created_at: :desc).paginate(page: params[:page])
end
def create
#card = #column.cards.build(card_params)
#card.user = current_user
if #card.save
flash[:success] = "Card was successfully created."
else
flash[:error] = #card.errors.full_messages.join("\n")
end
end
def update
if #card.update(card_params)
flash[:success] = "Card was successfully updated."
else
flash[:error] = #card.errors.full_messages.join("\n")
end
end
Thank you for your help.
As I understand it, you want to update your card, with just your card id? This can be done easily by changing your routes. I recommned using shallow nesting: https://guides.rubyonrails.org/routing.html#shallow-nesting.
# inside your routes.rb file - you can add exceptions
# as in the code you have posted above if you wish
resources :boards do
resources :columns, shallow: true do
resources :cards, shallow: true do
end
end
end
# now because you are using shallow editing you can simply do this:
edit_card_path(#card.id)
And when you want to update, you can do so easily by just using the card_id. You will not need your the board and column ids. It is hard to be more specific because you have not given the card_params nor any forms.
I have a user profile controller called "userinfo" and it's corresponding view. The userinfo index is the root path. In the homepage(which is the userinfo index), I have a link that takes you to the user profile page. It is giving me this error when I go to the home page:
My routes are:
My userinfos_controller:
class UserinfosController < ApplicationController
before_action :find_userinfo, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#userinfors = Userinfo.find(params[:id])
end
def show
#myvideo = Video.last
end
def new
#userinformation = current_user.userinfos.build
end
def create
#userinformation = current_user.userinfos.build(userinfo_params)
if #userinformation.save
redirect_to root_path
else
render 'new'
end
end
def edit
end
def update
end
def destroy
#userinformation.destroy
redirect_to userinfo_path
end
private
def userinfo_params
params.require(:userinfo).permit(:name, :email, :college, :gpa, :major)
end
def find_userinfo
#userinformation = Userinfo.find(params[:id])
end
end
and my view is:
<%= link_to 'profile', userinfors_path(#userinfors) %>
My routes.rb file:
Rails.application.routes.draw do
devise_for :users
resources :userinfos do
resources :videos
end
resources :pages
get '/application/decide' => 'application#decide'
root 'userinfos#index'
get '/userinfos/:id', to: 'userinfos#show', as: 'userinfors'
end
Thanks for any help!
ok, there are multiple errors and you are not following conventions of rails, index is not for what you have used.
Index is used to list all the users and show for a particular one with id passed in params.
Your index path is, as you can see, /userinfos which is correct and it doesn't have any id with it but you are trying to find user with params[:id] which is nil and hence the error.
Lets try out this:
def index
#userinfors = Userinfo.all #pagination is recommended
end
In your index view,
<% #userinfors.each do |userinfor| %>
<%= link_to "#{userinfor.name}'s profile", userinfo_path(userinfor) %>
<% end %>
It should work now.
Please read routing and action controller to get the idea and understand the magic behind rails routing and mvc architecture..
I've made a comments section for my 'posts' views and I've got remote: true working on the form so when you hit enter and submit the 'new comment' form to the database, it updates in the background fine (the comment is created, page doesn't redirect or change) but I can't get it to load the comments on the page. You have to refresh the page to see them.
I could do redirect_to :back in the comments controller after saving but that takes user to top of the page rather than staying put to see the comment appear.
I've tried render 'posts#show' after saving the comment in the comment controller create action but that tries to send you to /comments/posts/:slug/. If it actually rendered the posts show action I think this would work.
Comments controller:
class CommentsController < ApplicationController
before_action :find_commentable
def show
end
def new
#comment = Comment.new
end
def create
#comment = #commentable.comments.new comment_params
#comment.author = current_user if current_user
#comment.save
end
private
def comment_params
params.require(:comment).permit(:body, :author_id, :post_id)
end
def find_commentable
#commentable = Comment.find(params[:comment_id]) if params[:comment_id]
#commentable = Post.find_by_slug(params[:post_id]) if params[:post_id]
end
end
Comment section on post show view:
%ul#post-comments
= render 'comment_feed'
= form_for [#post, Comment.new], remote: true do |f|
= f.text_field :body, class: 'js-new-comment-field', placeholder: "Write a comment..."
posts/show.js.erb:
$("#post-comments").html("<%= escape_javascript render("comment_feed") %>");
Routes.rb:
resources :posts do
collection do
match 'search' => 'posts#search', via: [:get, :post], as: :search # For ransack search
end
resources :comments
end
resources :comments do
resources :comments # Replies on comments
end
Got it working!
This helped loads:
https://gemfile.wordpress.com/2014/03/06/rails-blog-comments-with-ajax/
I added this second match line to routes.rb and it's refreshing the page with the new comment now:
resources :posts do
collection do
match 'search' => 'posts#search', via: [:get, :post], as: :search
match '/comments/posts/:slug' => 'posts#show', via: [:get, :post], as: :comment
end
resources :comments
end
It's not ajax though: demo
I have a link on my #index view:
<%= link_to 'Export Calendar (ICS)', { controller: :tickets, action: :ics_export, format: :ics }, class: "class-needed right" %>
routes.rb that pertains to this:
resources :tickets
get 'tickets/calendar' => 'tickets#ics_export'
post 'tickets' => 'tickets#index'
patch 'tickets/:id/close' => 'tickets#close', as: 'close_ticket'
post 'tickets/:id' => 'ticket_comments#create'
My TicketsController that pertains:
before_action :set_ticket, only: [:show, :edit, :destroy, :update, :close]
def show
#ticket_comment = TicketComment.new
end
def ics_export
tickets = Ticket.all
respond_to do |format|
format.html
format.ics do
cal = Icalendar::Calendar.new
tickets.each do |ticket|
event = Icalendar::Event.new
event.dtstart = ticket.start
event.description = ticket.summary
cal.add_event(event)
end
cal.publish
render :text => cal.to_ical
end
end
end
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
And when I click the link, it takes me to /tickets/calendar.ics which is correct but I get the following error:
ActiveRecord::RecordNotFound in TicketsController#show
Couldn't find Ticket with 'id'=calendar
Extracted source (around line #83):
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
The #ticket = Ticket.find(params[:id]) is highlighted. Which make sense that it is failing to call a ticket with an id of calendar.
Request has parameters:
{"id"=>"calendar",
"format"=>"ics"}
How do I fix this error? Why is it calling the show action?
There is a footnote in the canonical Rails Routing from the Outside In to the effect:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action's route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
As commented, the fix is to specify get 'tickets/calendar' => ... ahead of resources :tickets. If the order of routes is in question, you can run rake routes, which, to the best of my knowledge, should render your routes in the order they are checked.
resources :recipes do
resource :like, module: :recipes
resources :comments, only: [:new, :create, :show, :index], module: :recipes
end
recipe_comments GET /recipes/:recipe_id/comments(.:format) recipes/comments#index
POST /recipes/:recipe_id/comments(.:format) recipes/comments#create
Comments are in /recipes/:id
Recipe Controller
def show
#recipe = Recipe.find(params[:id])
#comment = #recipe.comments.new
#clean_recipe = Sanitizer.new(#recipe)
end
Recipes::CommentsController
Theres a before action that finds recipe.
def create
#comment = #recipe.comments.new(comment_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to recipes_path
end
end
I've done
form_for([#article,#comment]) and form_for [#article,Comment.new]
and still the comment isn't persisted. I am wondering because of the module namespace, do I have to do something different?
Add logger.info 'I am inside create action in comments controller' inside the create action. If you see this logger message in the rails console, then the create action gets called. It means your routes are defined correctly, your form is using the right form helper.
the correct format is form_for([#recipe, #comment]) however, I had a length validation in my comment model which was failing to pass. I set too_short and too_long messages, however they didn't show up, which further confused me