Ruby on Rails: New post not saving on the blog - ruby-on-rails

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 :)

Related

How to download an uploaded stored file from the database in rails?

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) %>

Ruby on Rails 4: Can't edit posts or comments

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) %>

Rails nomethod error on create action

I have a create product page and an add photo page. Add photo page should add photos to a product that was just created.
I can get to add photo page /products/:product_id/pics(.:format) but I get an error on submit
ActiveRecord::RecordNotFound (Couldn't find Product without an ID):
photo controller
def create
#product = Product.find(params[:product_id]) # <--- error here
#photo = Photo.new
if #photo.valid?
#photo.product_id = #product.id
#photo.save!
respond_to do |format|
format.html { redirect_to product_path(#product) }
format.json { render json: #product }
end
else
redirect_to root_url, :notice => "Somehting went wrong!"
end
end
pics.html.haml
= form_for #photo, :html => { :multipart => true, :id => "fileupload" } do |f|
= f.file_field :upload
products controller
def pics
#product = Product.find(params[:product_id])
#photo = Photo.new
# #product.photos.build
end
full console error
Started POST "/photos" for 127.0.0.1 at 2013-07-09 02:11:11 -0400
Processing by PhotosController#create as JSON
Parameters: {"utf8"=>"✓", "authenticity_token"=>"K9jWB2D0bFUB5+KOCRKLUsuDGNLchjzCBCL1h1znOiQ=", "photo"=>{"upload"=>#>}}
Completed 404 Not Found in 1ms
ActiveRecord::RecordNotFound (Couldn't find Product without an ID):
app/controllers/photos_controller.rb:15:in `create'
console with sachins solution
Started POST "/photos" for 127.0.0.1 at 2013-07-09 02:55:25 -0400
Processing by PhotosController#create as JSON
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5RV+GUCvNEFrw7l3/ApqAlbK/XJP78LmDR2Hc+O0rQ0=", "product_id"=>"125", "photo"=>{"upload"=>#>}}
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", "125"]]
Redirected to http://google.com/
Completed 302 Found in 4ms (ActiveRecord: 0.1ms)
Started GET "/" for 127.0.0.1 at 2013-07-09 02:55:25 -0400
Processing by StaticPagesController#home as JSON
Rendered static_pages/home.html.haml within layouts/application (0.1ms)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."auth_token" IS NULL LIMIT 1
Completed 200 OK in 93ms (Views: 91.8ms | ActiveRecord: 0.3ms)
try this out: ---
photos controller
def new
#product = Product.find(params[:product_id])
#photo = Photo.new
#photo.product_id = #product.id
end
pics.html.haml
= form_for #photo, :html => { :multipart => true, :id => "fileupload" } do |f|
= f.file_field :upload
= hidden_field_tag 'product_id', #photo.product_id
Use form_for [#product, #photo] instead of just #photo in your form. Be sure to, of course, find the product using params[:product_id].
You need to nest your routes like this:
resources :products do
resources :photos
end
Otherwise you won't have a params[:product_id] on your request.
try in your form
form_for [#product, #photo]
error is there in accessing the product_id from params
use params[:product_id] instead params[:product][:product_id]
Just set the hidden_field_tag in form_for
eg:-
= hidden_field_tag 'product_id', #product.id

Sortable Table Row with Nested Resource

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.

Why does Rails 3 nested route ignore nesting resource?

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

Resources