Build a second step of a nested form? - ruby-on-rails

I try to build a nested form with two bearing (= post do push do reviews)
And I have this error :
Error generated
I would like to know if I have the good practices to succeed this creation ?
My code
Views/pushs/show:
<%= link_to 'Add comment', new_post_push_review_path(#push.post_id, #push) %>
Reviews/controller :
class ReviewsController < ApplicationController
before_action :authenticate_user!
before_action :find_post
before_action :find_push
def new
#review = Review.new
end
def create
#review = #post.push.reviews.create(review_params)
#review.post_id = #push.post_id
#review.push_id = #push.id
#review.user_id = current_user.id
if #review.save
redirect_to push_path(#push.post_id, #push)
else
render 'new'
end
end
private
def review_params
params.require(:review).permit(:rating, :comment)
end
def find_post
#post = Post.find(params[:post_id])
end
def find_push
#post = Post.find(params[:post_id])
#push = Push.find(params[:push_id])
end
end
Views/reviews/new:
<%= simple_form_for([#post, #post.push.reviews.build]) do |f| %>
<%= f.input :rating %>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>
& the routes :
resources :posts do
resources :pushs do
resources :reviews
end
end

Related

Comment created on articles page not saving to database

Not sure why comments created on _comment_form.html.erb is not being rendered on articles/:id
I'm referencing this youtube tutorial: https://www.youtube.com/watch?v=IUUThhcGtzc
Comments controller:
class CommentsController < ApplicationController
before_action :authenticate_user!
before_action :set_article
def create
#comment = #article.comments.create(params[:comment].permit(:content, :article_id, :user_id))
#comment.user = current_user
#comment.save
if #comment.save
redirect_to #article
else
redirect_to #article
end
end
private
def set_article
#article = Article.find(params[:article_id])
end
end
Articles controller:
class ArticlesController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :set_article, only: [:show, :edit, :update, :destroy]
def show
#comments = Comment.where(article_id: #article).order("created_at DESC")
end
private
def set_article
#article = Article.find(params[:id])
end
end
_comment.html.erb (from articles/show.html.erb)
<%= render 'comments/comment_form' %>
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>
_comment_form.html.erb
<% if user_signed_in? %>
<%= form_for ([#article, #article.comments.build]) do |f| %>
<div class="form-group">
<%= f.label :content %>
<%= f.text_area :content, class: 'form-control' %>
</div>
<%= f.submit 'Post Comment', class: 'btn btn-primary' %>
<% end %>
<% end %>
routes.rb
resources :articles do
resources :comments
end
Some considerations I would like to do:
#comment.save
if #comment.save
When you do that, you're saving twice. Calling #comment.save on if condition already saves the article and return true or false if it was successful. Also, replace .save for .save!, so it will raise an exception in case it doesn't save, so you can check the reason on rails server log.
Also, think it's unnecessary to do this:
#comments = Comment.where(article_id: #article).order("created_at DESC")
Since you already set the #article, you can access #article.comments, once you put has_many :comments on article model.
You can also check on rails console if the Article was created correctly. Create a new one, and get it like article = Article.last, then you can check article.comments.
Hope this helps!

How can I create a form without using resources (action :new, :create) in Rails?

This is my controller
class SchoolsController < ApplicationController
def teacher
#teacher = Teacher.new
end
def form_create
#teacher = Teacher.new(teacher_params)
if teacher.save
redirect_to schools_teacher_path
else
flash[:notice] = "error"
end
end
private
def teacher_params
params.require(:teacher).permit(:name)
end
end
This is my views/schools/teacher.html.erb
<%= form_for :teacher do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
I am new to Ruby on Rails, and not sure how to proceed.
You should move this to a TeachersController let me show you how:
First you need to create the controller, you can get this done by typing this on the terminal at the project root directory:
$ rails g controller teachers new
Then into your route file (config/routes.rb):
resources :teachers, only: [:new, :create]
After that go to the teachers_controller.rb file and add the following:
class TeachersController < ApplicationController
def new
#teacher = Teacher.new
end
def reate
#teacher = Teacher.new(teacher_params)
if #teacher.save
redirect_to schools_teacher_path
else
redirect_to schools_teacher_path, notice: "error"
end
end
private
def teacher_params
params.require(:teacher).permit(:name)
end
end
Then you can have the form at views/teachers/new.html.erb:
<%= form_for :teacher do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
Please let me know how it goes!

how to access child new form from parent index page in rails?

I am trying to fetch booking controller's new form, from the cab index page. how can i fetch it? how can access the new form from cab index page where i have shown all the cabs which are added..
cab controller
class CabsController < ApplicationController
before_action :find_cab, only: [:show, :edit, :update, :destroy]
def index
#cabs = Cab.all.order("created_at DESC")
end
def new
#cab = Cab.new
end
def show
#reviews = Review.where(cab_id: #cab.id).order("created_at DESC")
if #reviews.blank?
#avg_review=0
else
#avg_review=#reviews.average(:rating).round(2)
end
end
def edit
end
def create
#cab = Cab.new(cab_params)
if #cab.save
redirect_to #cab
else
render 'new'
end
end
def update
if #cab.update(cab_params)
redirect_to #cab
else
render 'edit'
end
end
def destroy
#cab.destroy
redirect_to root_path
end
private
def find_cab
#cab = Cab.find(params[:id])
end
def cab_params
params.require(:cab).permit(:name, :number_plate, :seat, :image)
end
end
booking controller
class BookingsController < ApplicationController
before_action :find_booking, only: [:show, :edit, :update, :destroy]
before_action :find_cab
def index
#bookings = Booking.where(cab_id: #cab.id).order("created_at DESC")
end
def new
#booking = Booking.new
end
def show
end
def edit
end
def create
#booking = Booking.new(booking_params)
#booking.user_id = current_user.id
#booking.cab_id = #cab.id
if #booking.save
redirect_to cab_booking_path(#cab, #booking)
else
render 'new'
end
end
def update
end
def destroy
end
private
def find_booking
#booking = Booking.find(params[:id])
end
def find_cab
#cab = Cab.find(params[:cab_id])
end
def booking_params
params.require(:booking).permit(:date, :address, :start_destination, :destination, :start_date, :end_date, :contact_no)
end
end
routes
resources :cabs do
resources :bookings
end
cab/index.html.erb
<div class="container">
<h2>All Cabs</h2>
<div class="row">
<% #cabs.each do |cab| %>
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<%= link_to image_tag(cab.image.url(:medium), class: 'image'), cab %><br>
Cab Name : <h4><%= cab.name %></h4>
<%= link_to "Book Now", new_cab_booking_path(#cab, #booking) %> # i wanted to create this link
</div>
</div>
<% end %>
</div>
<%= link_to "Add Cab", new_cab_path, class: 'btn btn-default' %>
the error i am getting is
No route matches {:action=>"new", :cab_id=>nil, :controller=>"bookings"} missing required keys: [:cab_id]
No route matches {:action=>"new", :cab_id=>nil,
:controller=>"bookings"} missing required keys: [:cab_id]
The problem is with this line
<%= link_to "Book Now", new_cab_booking_path(#cab, #booking) %>
which should be
<%= link_to "Book Now", new_cab_booking_path(cab) %>

action create couldn't be found for PostsController

I'm following a rails tutorial and need some help to proceed further. Problem is, once I fill out the form which has a title,body fields and hit submit, it has to redirect to the show.html.erb page instead it throws an error.
Error: The action 'create' could not be found for PostsController
routes.rb
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
get "/posts" => "posts#index"
post "/posts" => "posts#create"
get "/posts/show" => "posts#show", as: :show
get "/posts/new" => "posts#new"
end
posts_controller_tests.rb
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
new.html.erb
<h1>Create a new blog post</h1>
<div class="form">
<%= form_for Post.new do |f| %>
<%= f.label :title %>: <br>
<%= f.text_field :title %> <br> <br>
<%= f.label :body %>: <br>
<%= f.text_area :body %> <br> <br>
<%= f.submit %>
<% end %>
</div>
Any help on this would be appreciated.
Note: You are using posts_controller_tests.rb not posts_controller.rb. You are putting your controller code in test controller.
Try to move the code in app/controllers/posts_controller.rb:
class PostsController < ApplicationController
def index
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
redirect_to show_path
end
def show
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
Your create action always redirects you to the show action. It doesn't matter if your model was saved or not.
You have to check if the model was saved or not:
def create
#post = Post.new(post_params)
if #post.save
flash[:success] = 'Successfully saved'
redirect_to #post
else
render 'new'
end
end
If it wasn't saved, it renders the new action again.
Change your routes.rb to this:
Rails.application.routes.draw do
get "/pages/about" => "pages#about"
get "/pages/contact" => "pages#contact"
resources :posts
end
Moreover you should inherit your controller from ActionController::Base
so change first line of your controller to
class PostsController < ActionController::Base
and move the controller to app/controllers/posts_controller.rb

No route matches while creating nested resource in Rails

I am trying to create a new teacher for a specific school in my project and I got this error:
No route matches [POST] "/schools/3/teachers/new"
Here is my teachers_controller.rb:
class TeachersController < ApplicationController
def new
#teacher = Teacher.new
end
def create
#teacher = Teacher.new(teacher_params)
#teacher.save
redirect_to school_path(school)
end
private
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName)
end
end
schools_controller.rb:
class SchoolsController < ApplicationController
def show
#school = School.find(params[:id])
end
def new
#school = School.new
end
def edit
#school = School.find(params[:id])
end
def update
#school = School.find(params[:id])
if #school.update(school_params)
redirect_to #school
else
render 'edit'
end
end
def index
#schools = School.all
end
def create
#school = School.new(school_params)
if #school.save
redirect_to schools_path
else
render 'new'
end
end
def destroy
#school = School.find(params[:id])
#school.destroy
redirect_to schools_path
end
private
def school_params
params.require(:school).permit(:name)
end
end
routes.rb:
Rails.application.routes.draw do
resources :schools do
resources :teachers
end
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'welcome#index'
And teachers/new.html.erb:
<%= form_for :teacher, url: school_teachers_path(school) do |f| %>
<p>
<%= f.label :firstName %><br>
<%= f.text_field :firstName %>
</p>
<p>
<%= f.label :lastName %><br>
<%= f.text_field :lastName %>
</p>
<p>
<%= f.label :middleName %><br>
<%= f.text_field :middleName %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
As your teacher resource is nested under the school resource, so you need to pass the school when you try to create a teacher.
Try changing your new and create actions in teachers_controller.rb to something like this:
def new
#school = School.find(params[:school_id])
#teacher = #school.teachers.build
end
def create
#school = School.find(params[:school_id])
#teacher = #school.teachers.build(params[:teacher])
#teacher.save
redirect_to school_path(#school)
end
And, then change your form to this:
<%= form_for([#school, #teacher]) do %>
. . .
. . .
<% end %>
Try this in your form:
<%= form_for [school, Teacher.new] do |f| %>
The path you are posting to is for the index of teachers at a school:
school_teachers GET /schools/:school_id/teachers(.:format) teachers#index
I believe that it's a has_many belongs_to association. So you need to first change your teacher controller create action and new action.
class TeachersController < ApplicationController
def new
get_school
#teacher = #school.teachers.build
end
def create
get_school
#teacher = #school.teachers.build(teacher_params)
If #teacher.save
redirect_to school_path(school)
else
render 'new'
end
private
def teacher_params
params.require(:teacher).permit(:firstName, :lastName, :middleName)
end
def get_school
#school = School.find (params [:school_id])
end
end
Then in your form you 'll do :
<%= form_for([#school,#teacher]) do |f| %>
Hope this will help

Resources