Here is how my app is setup.
#app/models/category.rb
class Category < ActiveRecord::Base
belongs_to :user
has_many :forums
end
#app/models/forum.rb
class Forum < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :posts
end
#app/models/post.rb
class post < ActiveRecord::Base
belongs_to :user
belongs_to :forum
has_many :comments
end
#app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
I'm having issues with my comment records. I can display them and create them, but can't edit/delete them as I can't figure out which link to set.
Here's my config/routes.rb
Rails.application.routes.draw do
devise_for :users, :path => '', :path_names => {:sign_up => 'register', :sign_in => 'login', :sign_out => 'logout'}
resources :categories
resources :forums do
resources :posts do
resources :comments
end
end
root 'categories#index'
end
Here is my comments controller.
class CommentsController < ApplicationController
def create
#forum = Forum.find(params[:forum_id])
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:comment))
#comment.user_id = current_user.id if current_user
#comment.save
if #comment.save
redirect_to [#forum, #post]
else
render 'new'
end
end
def edit
#forum = Forum.find(params[:forum_id])
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
def update
#forum = Forum.find(params(:forum_id])
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
if #comment.update(params[:comment].permit(:comment))
redirect_to post_path(#post)
else
render 'edit'
end
end
def destroy
#forum = Forum.find(params[:foumd_id])
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
end
_comments.html.haml
.comment.clearfix
.content
%p.comment_content= comment.comment
%p.comment_author= comment.user.email
.buttons
= link_to "Edit", edit_forum_post_comment_path[#forum, #post]
I'm also having issues with editing my posts, I can create them no problem but can't edit them...
Posts controller
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#posts = Post.all
end
def show
end
def new
#forum = Forum.find(params[:forum_id])
#post = current_user.posts.build
end
def create
#forum = Forum.find(params[:forum_id])
#post = current_user.posts.build(post_params)
if #post.save
redirect_to [#forum, #post]
else
render 'new'
end
end
def edit
end
def update
#forum = Forum.find(params[:forum_id])
if #post.update(post_params)
redirect_to [#forum, #post]
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content)
end
end
Logs
I, [2015-11-15T16:10:25.073062 #18541] INFO -- : Started GET "/forums/1/posts/1/" for 24.220.125.144 at 2015-11-15 16:10:25 -0600
I, [2015-11-15T16:10:25.122253 #18541] INFO -- : Processing by PostsController#show as HTML
I, [2015-11-15T16:10:25.122482 #18541] INFO -- : Parameters: {"forum_id"=>"1", "id"=>"1"}
D, [2015-11-15T16:10:25.148865 #18541] DEBUG -- : ^[[1m^[[36mPost Load (0.5ms)^[[0m ^[[1mSELECT `posts`.* FROM `posts` WHERE `posts$
D, [2015-11-15T16:10:25.185328 #18541] DEBUG -- : ^[[1m^[[35m (0.4ms)^[[0m SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id$
D, [2015-11-15T16:10:25.187051 #18541] DEBUG -- : ^[[1m^[[36mComment Load (0.3ms)^[[0m ^[[1mSELECT `comments`.* FROM `comments` WHER$
D, [2015-11-15T16:10:25.210686 #18541] DEBUG -- : ^[[1m^[[35mUser Load (0.4ms)^[[0m SELECT `users`.* FROM `users` WHERE `users`.`id$
I, [2015-11-15T16:10:25.232349 #18541] INFO -- : Rendered comments/_comment.html.haml (35.4ms)
I, [2015-11-15T16:10:25.232600 #18541] INFO -- : Rendered posts/show.html.haml within layouts/application (69.7ms)
I, [2015-11-15T16:10:25.233044 #18541] INFO -- : Completed 500 Internal Server Error in 110ms (ActiveRecord: 7.1ms)
F, [2015-11-15T16:10:25.235567 #18541] FATAL -- :
ActionView::Template::Error (No route matches {:action=>"edit", :controller=>"comments", :forum_id=>"1", :id=>"1"} missing required key$
3: %p.comment_content= comment.comment
4: %p.comment_author= comment.user.email
5: .buttons
6: = link_to "Edit", edit_forum_post_comment_path[#forum, #post]
app/views/comments/_comment.html.haml:6:in `_app_views_comments__comment_html_haml___1270861655862681835_22931440'
app/views/posts/show.html.haml:5:in `_app_views_posts_show_html_haml__2051422644921131492_20982460'
I, [2015-11-15T16:10:28.372822 #18541] INFO -- : Started GET "/forums/1/posts/1/edit" for 24.220.125.144 at 2015-11-15 16:10:28 -0600
I, [2015-11-15T16:10:28.375577 #18541] INFO -- : Processing by PostsController#edit as HTML
I, [2015-11-15T16:10:28.375656 #18541] INFO -- : Parameters: {"forum_id"=>"1", "id"=>"1"}
D, [2015-11-15T16:10:28.377175 #18541] DEBUG -- : ^[[1m^[[36mPost Load (0.4ms)^[[0m ^[[1mSELECT `posts`.* FROM `posts` WHERE `posts$
D, [2015-11-15T16:10:28.379458 #18541] DEBUG -- : ^[[1m^[[35mUser Load (0.3ms)^[[0m SELECT `users`.* FROM `users` WHERE `users`.`id$
I, [2015-11-15T16:10:28.403726 #18541] INFO -- : Rendered posts/_form.html.haml (20.6ms)
I, [2015-11-15T16:10:28.403924 #18541] INFO -- : Rendered posts/edit.html.haml within layouts/application (22.8ms)
I, [2015-11-15T16:10:28.404187 #18541] INFO -- : Completed 500 Internal Server Error in 28ms (ActiveRecord: 0.7ms)
F, [2015-11-15T16:10:28.405890 #18541] FATAL -- :
ActionView::Template::Error (undefined method `post_path' for #:0x00000003e04f18>):
1: = simple_form_for [#forum,#post] do |f|
2: = f.input :title
3: = f.input :content
4: = f.submit
app/views/posts/_form.html.haml:1:in `_app_views_posts__form_html_haml__3317057176452412006_32596640'
app/views/posts/edit.html.haml:3:in `_app_views_posts_edit_html_haml__3955498671314368903_32545500'
The error is as follows:
ActionView::Template::Error (No route matches {:action=>"edit", :controller=>"comments", :forum_id=>"1", :id=>"1"} missing required key$
ActionView::Template::Error (undefined method `post_path' for #:0x00000003e04f18>):
When asking questions / debugging in general, you need to start with the error / problem.
You've put up so much code most people will turn their noses up.
--
The error suggests a problem with your routes:
#config/routes.rb
Rails.application.routes.draw do
resources :categories
resources :forums do
resources :posts do
resources :comments
end
end
root 'categories#index'
end
The issue appears to be the way you're nesting your forms / posts / comments:
The first error is because you've not passed the post_id:
<%= link_to "Edit Comment", edit_forum_post_comment_path(#forum, #post, #comment) %>
The second error is because (I think) you've called your path without having the #forum variable populated. You should make sure that #forum is populated as follows:
#forum = Forum.find params[:forum_id]
#post = Post.new
Alternatively, you could build the post object on the #forum object, like so:
#forum = Forum.find params[:forum_id]
#post = #forum.posts.build
This should allow you to call <%= form_for #post do |f| %>
As a secondary to this, you need to look up the limits to nesting, as it deals directly with your problem:
Resources should never be nested more than 1 level deep.
Whilst I'd have to spend some time thinking about the best way to fix your issue, I'd do something like the following:
#config/routes.rb
resources :forums do
resources :posts, :comments
end
This will set the comments directly below the forums resource, allowing you to skip having to associate a forum and post each time you want to do anything with them...
<%= link_to "Edit Comment", edit_forums_comments_path(#forum, #comment) %>
Related
Im trying to implement a download functionality to an uploaded pdf file in my app. For some reason the record can not be found? If I check the GET Request I see that it tries to use the url ending "/resumes/download.5". 5 is the record id from the stored file. What am I missing? How can I debug issues like that in the future? Byebug did not work this time for some reason.
views/resumes/show.html.erb
<%= link_to "Download", resume_download_path(#resume) %>
resumes_controller.rb
class ResumesController < ApplicationController
around_filter :catch_not_found
before_action :find_resume, only: [ :show, :edit, :update, :destroy, :download ]
before_action :authenticate_user!
def show
end
def new
if #resume = current_user.resume
redirect_to #resume
else
#resume = Resume.new
end
end
def create
#resume = current_user.build_resume(resume_params)
if #resume.save
redirect_to #resume
else
render :new
end
end
def edit
end
def update
if #resume.update resume_params
redirect_to #resume, notice: "Your resume was successfully saved!"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to new_resume_path, notice: "Your resume was successfully deleted!"
end
def download
send_data #resume, type: "application/pdf", disposition: "attachment"
end
private
def resume_params
params.require(:resume).permit( :user_id, :download_file, :remove_download_file)
end
def find_resume
#resume = Resume.find(params[:id])
end
def catch_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to(root_url, :notice => 'Record not found')
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
root 'welcomes#index'
resources :resumes
get "resumes/download", as: "resume_download"
get '*path' => redirect('/')
end
When clicking on the download link:
Started GET "/resumes/download.5" for 77.8.13.5 at 2017-08-23 21:22:14 +0000
Cannot render console from 77.8.13.5! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by ResumesController#show as
Parameters: {"id"=>"download"}
Resume Load (0.2ms) SELECT "resumes".* FROM "resumes" WHERE "resumes"."id" = ? LIMIT 1 [["id", 0]]
Redirected to https://rails-tutorial-martinbortowski.c9.io/
Completed 302 Found in 3ms (ActiveRecord: 0.2ms)
Started GET "/" for 77.8.13.5 at 2017-08-23 21:22:15 +0000
Cannot render console from 77.8.13.5! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by WelcomesController#index as HTML
Rendered welcomes/index.html.erb within layouts/application (0.2ms)
Completed 200 OK in 39ms (Views: 38.4ms | ActiveRecord: 0.0ms)
resources :resumes do
get :download, on: :member
end
Will give you an idiomatically correct REST route:
resumes/:id/download
Change your link to:
<%= link_to "Download", download_resume_path(#resume), "data-turbolinks" => false %>
See Rails Routing from the Outside In - Adding More RESTful Actions.
You download link seems to be wrong.
change in your routes.rb
get "resumes/download", as: "resume_download"
to
controller :resumes do
get "resumes/download/:id" => :show, as: :resume_download
end
views/resumes/show.html.erb
change your link
<%= link_to "Download", resume_download_path(#resume) %>
to
<%= link_to "Download", resume_download_path(id: #resume) %>
I'm working on an exercise, creating a blog with ruby on rails. I have the form ready to post an article, but once I click on the submit button, I am redirected to the homepage but the article doesn't save. Here is the following code
class ArticlesController < ApplicationController
def index
#articles = Article.paginate(:page => params[:page], per_page: 5).order('created_at DESC')
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(title: params.permit[:title], body: params.permit[:body])
if #article.save
redirect_to articles, :notice => "Your post has been saved"
else
render :create
end
end
end
Here is the view create.html.haml
.container
.row
.col-xs-9-
.panel-title
%h2 Ecrivez votre article
= form_for #article do |f|
= f.text_field :title
= f.text_area :body, size: "60x12"
= f.submit "Publier"
Then the route.rb, I don't know if it can help
TP2::Application.routes.draw do
resources :articles, only: [:index]
get 'articles' => 'articles#index'
get 'articles/:id' => 'articles#show'
get 'articles/new'
get 'post' => 'articles#create'
post 'articles' => 'articles#index'
And to finish here is what the console show when I try to post an article
Started GET "/post" for 127.0.0.1 at 2016-04-10 14:24:56 +0200
Processing by ArticlesController#create as HTML
(0.2ms) BEGIN
(0.2ms) ROLLBACK
Rendered articles/create.html.haml within layouts/application (1.4ms)
Completed 200 OK in 9ms (Views: 4.9ms | ActiveRecord: 0.4ms)
Started POST "/articles" for 127.0.0.1 at 2016-04-10 14:25:10 +0200
Processing by ArticlesController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FMQmKvZ1t98ZE21VaiBQhm0jKJ9x9BwkXFbh4obfi3Qea0Zax5dgGirfpgcAiQA464GMD2+Qv/eGYrmvEoTZBQ==", "article"=>{"title"=>"Post", "body"=>"New Article test"}, "commit"=>"Publier"}
Article Load (0.6ms) SELECT "articles".* FROM "articles" ORDER BY created_at DESC LIMIT 5 OFFSET 0
(0.4ms) SELECT COUNT(*) FROM "articles"
Rendered articles/index.html.haml within layouts/application (3.4ms)
Completed 200 OK in 7ms (Views: 5.3ms | ActiveRecord: 1.0ms)
I don't understand why the new article won't save. Does anyone understand why ?
I would simplify the routes:
Rails.application.routes.draw do
root to: 'articles#index' # or where you want for the first page
resources :articles #will give you the correct path and verbs
end
And the articles_controller.rb
class ArticlesController < ApplicationController
...
def create
#article = Article.new(article_params)
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: "Article created!" }
else
format.html { render action: 'new' }
end
end
end
private
def article_params
params.require(:article).permit(:title, :body)
end
end
Because you are learning new stuff, this is a way you should use to debug your code:
put a binding.pry (a breakpoint) on the line before #article.save (or use another debugger, you can find it on Github)
reload your page, input the fields and click Save
go to the rails console, issue #article.save on the console (or #article.valid?), it should return false
puts #article.errors, so you can what are the validation issues
Good luck :)
I know this is the most commonly asked question but i am really looking for some help here as i don't understand what i am doing wrong here .
I have a generated a devise user and intend to create a gallery for users . Following is the code i have tried
Model - Gallery.rb
class Gallery < ActiveRecord::Base
belongs_to :user
end
Controller - galleries_controller.rb
class GalleriesController < ApplicationController
before_action :set_gallery, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!
respond_to :html
def index
#user = User.find(params[:user_id])
#galleries = Gallery.all
respond_with(#galleries)
end
def show
respond_with(#gallery)
end
def new
#user = User.find(params[:user_id])
#gallery = Gallery.new
respond_with(#gallery)
end
def edit
end
def create
#gallery = Gallery.new(gallery_params)
flash[:notice] = 'Gallery was successfully created.' if #gallery.save
respond_with(#gallery)
end
def update
flash[:notice] = 'Gallery was successfully updated.' if #gallery.update(gallery_params)
respond_with(#gallery)
end
def destroy
#gallery.destroy
respond_with(#gallery)
end
private
def set_gallery
#gallery = Gallery.find(params[:id])
end
def gallery_params
params[:gallery, :user_id]
end
end
Folowing is the error that gets shown with better errors -
Logs
Started GET "/galleries/1" for 127.0.0.1 at 2015-05-03 15:24:10 +0530
Processing by GalleriesController#show as HTML
Parameters: {"id"=>"1"}
Gallery Load (2.1ms) SELECT "galleries".* FROM "galleries" WHERE "galleries"."id" = ? LIMIT 1 [["id", 1]]
Completed 404 Not Found in 63ms
ActiveRecord::RecordNotFound - Couldn't find Gallery with 'id'=1:
activerecord (4.2.0) lib/active_record/core.rb:154:in `find'
routes.rb
Rails.application.routes.draw do
root to: 'visitors#index'
devise_for :users
resources :users do
resources :galleries
resources :photos
end
end
As i am still new to ROR , any help would be very much appreciated . Thanks in advance .
From the URL i am assuming you are not passing user_id in params.
In your route file gallery should be nested route. If you wan't user_id.
resources :users do
resources :galleries do
end
end
or you can use
#user= current_user
In my rails app, a Timesheet has_many Entries and an Entry belongs_to a Timesheet.
class Timesheet < ActiveRecord::Base
has_many :entries, order: 'position', dependent: :destroy
end
class Entry < ActiveRecord::Base
belongs_to :timesheet
end
I'm following Railscast 147 for sortable lists (the updated version). In the development log I notice that my params hash correctly updates the sort order, but on reload it doesn't save the positions correctly. Furthermore, the request is being processed by the create action instead of my custom sort action. Here's my controller.
class EntriesController < ApplicationController
before_filter :signed_in_user
before_filter :find_timesheet
def index
#entries = #timesheet.entries.order("position")
#entry = #timesheet.entries.build
end
def create
#entry = #timesheet.entries.build(params[:entry])
#entry.position = #timesheet.entries.count + 1
if #entry.save
#flash[:notice] = "Entry created"
#redirect_to timesheet_entries_path
respond_to do |format|
format.html { redirect_to timesheet_entries_path }
format.js
end
else
flash[:alert] = "Entry could not be added"
render 'new'
end
end
def destroy
#entry = #timesheet.entries.find(params[:id])
#entry.destroy
respond_to do |format|
format.html { redirect_to timesheet_entries_path, flash[:notice] = "Entry destroyed" }
format.js
end
end
def sort
params[:entry].each_with_index do |id, index|
#timesheet.entries.update_all({position: index+1}, {id: id})
end
render nothing: true
end
private
def find_timesheet
#timesheet = Timesheet.find(params[:timesheet_id])
end
end
and my routes.rb file.
Sledsheet::Application.routes.draw do
resources :timesheets do
resources :entries, only: [:index, :create, :destroy] do
collection { post :sort }
end
end
end
The entries.js.coffee
jQuery ->
$("#entries tbody").sortable(
helper: fixHelper
update: ->
$.post($(this).data('update-url'), $(this).sortable('serialize'))
).disableSelection()
The output from the development log
Started POST "/timesheets/8/entries" for 127.0.0.1 at 2012-06-04 20:14:18 -0400
Processing by EntriesController#create as */*
Parameters: {"entry"=>["60", "59", "61"], "timesheet_id"=>"8"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'qDs53hgOWfRMbNN9JKau3w' LIMIT 1
Timesheet Load (0.1ms) SELECT "timesheets".* FROM "timesheets" WHERE "timesheets"."id" = ? ORDER BY date DESC LIMIT 1 [["id", "8"]]
Completed 500 Internal Server Error in 2ms
NoMethodError (undefined method `stringify_keys' for "60":String):
app/controllers/entries_controller.rb:11:in `create'
I googled the error about the undefined method, but I'm confused why the create action would be called in this case anyway? I do have a new_entry form on the page, that creates a new entry via Ajax. Perhaps this is interfering with the sort? Any help would be appreciated!
The reason why there's no 'stringify_keys' method is because you're passing an array to the create action and not the sort action.
What do you have for data-update-url in your erb.html file?
Should be sort_entries_path.
Associations:
location has_many :comments
comment belongs_to :location
For some reason, this GET:
/locations/5/comments.json
is acting like this GET:
/comments.json
Started GET "/locations/5/comments.json" for 127.0.0.1 at 2012-04-10 21:18:00 -0700
Processing by CommentsController#index as JSON
Parameters: {"location_id"=>"5"}
Comment Load (0.1ms) SELECT "comments".* FROM "comments"
Completed 200 OK in 21ms (Views: 1.0ms | ActiveRecord: 0.7ms)
Note the SQL query: SELECT "comments".* FROM "comments"
The route is set up like this:
resources :locations do
resources :comments
end
Rake routes confirms the route:
location_comments GET /locations/:location_id/comments(.:format) {:action=>"index", :controller=>"comments"}
Here is the index action:
def index
#comments = Comment.all
respond_to do |format|
format.json { render json: #comments }
end
end
Is this the right action? It is consistent with the result, but I am not sure what else should be here. I've never had a problem with nested resources before, so I've never looked into the details.
try this:
def index
#location = Location.find(params[:location_id])
#comments = #location.comments
respond_to do |format|
format.json { render json: #comments }
end
end