I want to build a for loop but I an this error.
undefined method `each' for nil:NilClass
That is the part of the view, which gives me the error:
<% #deadlines.each do |deadline| %>
<% if Time.now < deadline.deadline %>
<%= form_for(current_user) do |f| %>
<%= f.hidden_field :enrolled, :value => true %>
<%= f.submit "Anmeldung bestätigen", class: "btn btn-primary" %>
<% end %>
<% end %>
<% end %>
Seems like #deadlines is not recognized, even though I already used the same loop in the Index view of the deadlines folder. How can I use the same variable in my homepage view?
Thanks a lot!
Here is the Controller, maybe it also gives you some information:
class DeadlinesController < ApplicationController
before_action :set_deadline, only: [:show, :edit, :update, :destroy]
# GET /deadlines
# GET /deadlines.json
def index
#deadlines = Deadline.all
end
# GET /deadlines/1
# GET /deadlines/1.json
def show
end
# GET /deadlines/new
def new
#deadline = Deadline.new
end
# GET /deadlines/1/edit
def edit
end
# POST /deadlines
# POST /deadlines.json
def create
#deadline = Deadline.new(deadline_params)
respond_to do |format|
if #deadline.save
format.html { redirect_to #deadline, notice: 'Deadline was successfully created.' }
format.json { render :show, status: :created, location: #deadline }
else
format.html { render :new }
format.json { render json: #deadline.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /deadlines/1
# PATCH/PUT /deadlines/1.json
def update
if #deadline.update(deadline_params)
flash[:success] = "Die Deadline wurde erfolgreich aktualisiert."
redirect_to deadlines_path
else
flash[:error] = "Die Deadline wurde nicht aktualisiert."
end
end
# DELETE /deadlines/1
# DELETE /deadlines/1.json
def destroy
#deadline.destroy
respond_to do |format|
format.html { redirect_to deadlines_url, notice: 'Deadline was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_deadline
#deadline = Deadline.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def deadline_params
params.require(:deadline).permit(:deadline)
end
end
Your #deadlines is empty now, use this #deadlines = Deadline.all to your homepage controller action and each block modify like this
<% if #deadlines.present? %>
<% #deadlines.each do |deadline| %>
<% if Time.now < deadline.deadline %>
<%= form_for(current_user) do |f| %>
<%= f.hidden_field :enrolled, :value => true %>
<%= f.submit "Anmeldung bestätigen", class: "btn btn-primary" %>
<% end %>
<% end %>
<% end %>
<% else %>
Deadline is empty
<% end %>
When #deadlines is empty then it will show Deadline is empty
Related
i created an edit page to edit the room(model) and update the form to change the current name and current capacity to whatever we wish but i am getting an error
ActionController::ParameterMissing in RoomsController#edit
param is missing or the value is empty: room
rooms_controller.rb
class RoomsController < ApplicationController
before_action :set_room, only: %i[show edit update]
def index
#rooms = Room.all
end
def show
end
def new
#room = Room.new
end
def create
#room = Room.new(room_params)
respond_to do |format|
if #room.save
format.html { redirect_to room_url(#room), notice: "Room was created Successfully" }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
def edit
respond_to do |format|
if #room.update(room_params)
format.html { redirect_to room_url(#room), notice: "Room was successfully updated!" }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
private
def set_room
#room = Room.find(params[:id])
end
def room_params
params.require(:room).permit(:name, :capacity)
end
end
edit.hml.erb
<h2>Edit Room</h2>
<%= render "form", room: #room %>
_form.html.erb
<%= form_with(model: room) do |form| %>
<% if room.errors.any? %>
<div style="color: red">
<h2><%= pluralize(room.errors.count, "errors") %> Prohibited this Room from saving</h2>
<ul>
<% room.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :name, style: "display: block" %>
<%= form.text_field :name %>
</div>
<div>
<%= form.label :capacity, style: "display: block" %>
<%= form.number_field :capacity %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
i am using the same partial _form.html.erb for both new.html.erb and edit.html.erb , is it because of using same partial form for edit and new or there is some other reason?
new.html.erb
<h1>New Room</h1>
<%= render "form", room: #room %>
You're using the wrong action.
In Rails flavored REST the edit action responds to a GET /rooms/:id/edit request and just renders the form. It should also be idempotent. There is no room parameter since you're not responding to a form submission.
Updating the resource is done in the update method (PATCH /rooms/:id).
class RoomsController < ApplicationController
# ...
# you can actually completely omit this method
# Rails will implicitly render edit.html.erb anyways
# GET /rooms/1/edit
def edit
end
# PATCH /rooms/1
def update
# you don't need to use MimeResponds if you're only responding to HTML requests. KISS
if #room.update(room_params)
redirect_to #room, notice: "Room was successfully updated!"
else
render :edit, status: :unprocessable_entity
end
end
# ...
end
So I have clients page, services page and using a bookable gem. So currently when I click "Book" besides a customers name, a booking form pops up which allows me to choose a date and time and the length of the appointment. However, with this form I would like to also be able to choose the service that the appointment needs, so once a service has been added, a drop down list on the bookings form will show the services which have been added. (Hopefully that made sense)
Is there any chance someone could please help me with how I can do this?
Bookings (_form.html.erb)
<%= form_for([#client, #booking]) do |f| %>
<p>
<%= f.label 'start_time', 'Start time' %>
<%= f.datetime_select :start_time, { minute_step: 15 } %>
</p>
<p>
<%= f.label 'length', 'Length of booking in hours' %>
<%= f.number_field 'length', min: 1 %>
</p>
<%= f.submit 'Submit' %>
<% end %>
Services (index.html.erb)
<h1>Services <%= link_to "+ New", new_service_path %></h1>
<table>
<div class="row">
<div class="hidden-xs col-sm-3">
<h3>Name</h3>
</div>
<div class="hidden-xs col-sm-3">
<h3>Description</h3>
</div>
<div class="hidden-xs col-sm-3">
<h3>Price</h3>
</div>
<div class="hidden-xs col-sm-3">
<h3>Service Duration</h3>
</div>
</div>
<tbody>
<% #services.each do |service| %>
<tr>
<td><%= service.name %></td>
<td class="tb1"><%= service.description %></td>
<td class="tb2"><%= service.price %></td>
<td class="tb3"><%= service.duration %></td>
<td><%= link_to 'Show', service %></td>
<td><%= link_to 'Edit', edit_service_path(service) %></td>
<td><%= link_to 'Destroy', service, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
bookings_controller.rb
class BookingsController < ApplicationController
respond_to :html, :xml, :json
before_action :find_client
def index
#bookings = Booking.where("client_id = ? AND end_time >= ?", #client.id, Time.now).order(:start_time)
respond_with #bookings
end
def new
#booking = Booking.new(client_id: #client.id)
end
def create
#booking = Booking.new(params[:booking].permit(:client_id, :start_time, :length))
#booking.client = #client
if #booking.save
redirect_to client_bookings_path(#client, method: :get)
else
render 'new'
end
end
def show
#booking = Booking.find(params[:id])
end
def destroy
#booking = Booking.find(params[:id]).destroy
if #booking.destroy
flash[:notice] = "Booking: #{#booking.start_time.strftime('%e %b %Y %H:%M%p')} to #{#booking.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
redirect_to client_bookings_path(#client)
else
render 'index'
end
end
def edit
#booking = Booking.find(params[:id])
end
def update
#booking = Booking.find(params[:id])
# #booking.clients = #clients
if #booking.update(params[:booking].permit(:client_id, :start_time, :length))
flash[:notice] = 'Your booking was updated succesfully'
if request.xhr?
render json: {status: :success}.to_json
else
redirect_to client_bookings_path(#client)
end
else
render 'edit'
end
end
private
def save booking
if #booking.save
flash[:notice] = 'booking added'
redirect_to client_booking_path(#client, #booking)
else
render 'new'
end
end
def find_client
if params[:client_id]
#client = Client.find_by_id(params[:client_id])
end
end
end
services_controller.rb
class ServicesController < ApplicationController
before_action :set_service, only: [:show, :edit, :update, :destroy]
# GET /services
# GET /services.json
def index
#services = Service.all
end
# GET /services/1
# GET /services/1.json
def show
end
# GET /services/new
def new
#service = Service.new
end
# GET /services/1/edit
def edit
end
# POST /services
# POST /services.json
def create
#service = Service.new(service_params)
respond_to do |format|
if #service.save
format.html { redirect_to #service, notice: 'Service was successfully created.' }
format.json { render :show, status: :created, location: #service }
else
format.html { render :new }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /services/1
# PATCH/PUT /services/1.json
def update
respond_to do |format|
if #service.update(service_params)
format.html { redirect_to #service, notice: 'Service was successfully updated.' }
format.json { render :show, status: :ok, location: #service }
else
format.html { render :edit }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
# DELETE /services/1
# DELETE /services/1.json
def destroy
#service.destroy
respond_to do |format|
format.html { redirect_to services_url, notice: 'Service was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_service
#service = Service.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def service_params
params.require(:service).permit(:name, :description, :price, :duration)
end
end
So as far as i can tell, what you want is on the bookings form (ie the new action) you'd like to display a drop-down that has all of the services so it can be chosen. Then when they submit this, they add that service to their booking?
Well, firstly - you'd need to add service_id as a column to your bookings table and the association in the Booking class.
I'd recommend using the specialised migration for associations: references eg:
class AddServiceToBookings < ActiveRecord::Migration[5.0]
def change
add_reference :bookings, :service, foreign_key: true
end
end
It's a good idea to then add the association to your booking class:
class Booking < ActiveRecord::Base
belongs_to :service
Then you can show the collection of services in the service-drop-down in the form using collection_select:
<%= form_for([#client, #booking]) do |f| %>
<p>
<%= f.label 'start_time', 'Start time' %>
<%= f.datetime_select :start_time, { minute_step: 15 } %>
</p>
<p>
<%= f.label 'length', 'Length of booking in hours' %>
<%= f.number_field 'length', min: 1 %>
</p>
<p>
<%= f.label 'service_id', 'Service' %>
<%= f.collection_select :service_id, Service.all, :id, :name %>
</p>
<%= f.submit 'Submit' %>
<% end %>
Then you'll need to allow the service_id in your permit/require section of your bookings controller:
#booking = Booking.new(params[:booking].permit(:client_id, :service_id, :start_time, :length))
And you might need some more tweaking here and there, but this is the gist of it.
I've been stuck on this all day. When I try to show the details of a job, create a job, or edit a current job in my ruby on rails project I get a NoMethodError in Jobs#show on the second last line explaining there is a problem with the link to the edit page.
Jobs/show.html
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #job.name %>
</p>
<p>
<strong>Employer:</strong>
<%= #job.employer %>
</p>
<p>
<strong>Sector:</strong>
<%= #job.sector_id %>
</p>
<p>
<strong>Experience req:</strong>
<%= #job.experience_req %>
</p>
<p>
<strong>Job info:</strong>
<%= #job.job_info %>
</p>
<h2>Star comment: </h2>
<%=form_for([#job, Request.new]) do |f| %>
</h3></br>
<%= f.text_area:content, :rows => 4, :cols=> 40%>
<div class = "actions">
<%=f.submit "Make a request for the job"%>
</div>
<% end %>
<%if #job.requests.empty? %>
<h3> You are the first to Request</h3>
<% else %>
<h2> Who else had made a request for this job:</h2>
<% #job.requests.reverse.each do |request| %>
<p><%= request.content %>
Posted <%=time_ago_in_words(request.created_at)%> ago by
<%=request.candidate.can_name%></p>
<% end %>
<% end %>
<%= link_to 'Edit', edit_jobs_path(#job) %> | **This line highlights an error**
<%= link_to 'Back', jobs_path %>
Jobs/edit.html
<h1>Editing job</h1>
<%= render 'form' %>
<%= link_to 'Show', #job %> |
<%= link_to 'Back', jobs_path %>
Routes
Rails.application.routes.draw do
# get 'sessions/new'
# get 'sessions/create'
#get 'sessions/destroy'
controller :sessions do
get 'login' =>:new
post 'login' =>:create
get 'logout' =>:destroy
delete 'logout' =>:destroy
end
#get 'pages/home'
#get 'pages/about'
resources :candidates
resources :requests
resources :employers
resources :jobs
resources :sectors
# 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 'pages#home'
#root :to=>'pages#home
#'welcome#index'
resources :jobs do
resources :requests
end
end
Jobs_Controller
class JobsController < ApplicationController
before_action :set_job, only: [:show, :edit, :update, :destroy]
# GET /jobs
# GET /jobs.json
def index
#jobs = Job.all
end
# GET /jobs/1
# GET /jobs/1.json
def show
end
# GET /jobs/new
def new
#job = Job.new
end
# GET /jobs/1/edit
def edit
end
# POST /jobs
# POST /jobs.json
def create
#job = Job.new(job_params)
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Job was successfully created.'
}
format.json { render :show, status: :created, location: #job }
else
format.html { render :new }
format.json { render json: #job.errors, status: :unprocessable_entity
}
end
end
end
# PATCH/PUT /jobs/1
# PATCH/PUT /jobs/1.json
def update
respond_to do |format|
if #job.update(job_params)
format.html { redirect_to #job, notice: 'Job was successfully updated.'
}
format.json { render :show, status: :ok, location: #job }
else
format.html { render :edit }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jobs/1
# DELETE /jobs/1.json
def destroy
#job.destroy
respond_to do |format|
format.html { redirect_to jobs_url, notice: 'Job was successfully
destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_job
#job = Job.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white
#list through.
def job_params
params.require(:job).permit(:name, :employer, :sector_id,
:experience_req,:job_info)
end
end
Update
Ursus informed me I had to change <%= link_to 'Show', #job %> to<%= link_to 'Show', job_path(#job) %> in Jobs/edit.html. I did this, however when I try to create a new job or edit a current job I still get the same error but the new job is still created?
This
<%= link_to 'Show', #job %>
should be
<%= link_to 'Show', job_path(#job) %>
I'm working on creating a survey app where surveys can have many questions and questions can have many surveys. What I'd like to do is on the survey show page display a button "Add new question" that allows a user to add a new question to that survey. So in my code I send the survey id like this:
<%= link_to "Add Question", new_question_path(:survey_id => #survey.id)%>
Then I can set #survey using the params I'm sending in my question controller. This is working fine in my :new method, but is throwing a nil error when I try to call in the :create method. I believe this is because a new instance of the controller is getting created which no longer has access to the :survey_id param I sent initially.
So I'm wondering if there is anyway to pass along the params to the next instance of the controller? Or is there a better way to send which survey should be set for that question? Is this something I could "save" in a hidden field? I thought about trying to save something in my model, but to save a question earlier would require me to remove the validations I have.
Here's my question_controller:
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
before_action :set_survey, only: [:new, :create]
# GET /questions
# GET /questions.json
def index
#questions = Question.all
end
# GET /questions/1
# GET /questions/1.json
def show
#answers = #question.answers
end
# GET /questions/new
def new
#question = Question.new
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
def create
#question = Question.new(question_params)
respond_to do |format|
if #question.save
#survey.questions << #question
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
format.html { redirect_to questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
def set_survey
#survey = Survey.find(params[:survey_id])
flash[:alert] = "Survey is " + #survey.to_s
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :single_response, :surveys, :surveytizations)
end
end
And the form I'm creating the question with:
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :single_response %><br>
<%= f.check_box :single_response %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Thanks! Any help is very much appreciated!
UPDATE:
I was able to work using Rails.cache.write/Rails.cache.read - How to pass values between controller methods
Is there anything wrong with doing it that way or is that the best route?
I think you need to store the survey_id in a hidden field. Then you can access it from the questions controller. In your view:
<%= form_for(#question) do |f| %>
<%= f.hidden_field :survey_id %>
#rest of form
You also might have to change your new action to something like this:
#question = Question.new(:survey_id => params[:survey_id])
If the questions always belongs to a survey it could be a good idea to nest the routes so that you always can check which survey you are working on.
I have a class called "questions", which is similar to an article, and each of them can have comments. Now the problem is, that I want to show multiple questions on the index page and all displaying the comments of the specific question as well as a small little form to leave a comment, which should be added to its question. Basically I have added the form and done everything, apart from figuring out how to get the question id and pass it to the comment.
I have made a little screenshot as well: http://prntscr.com/2pjk0i
questions_controller.rb
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
# GET /questions
# GET /questions.json
def index
#current_user ||= User.find_by_id(session[:user_id])
#questions = Question.all
end
# GET /questions/1
# GET /questions/1.json
def show
end
# GET /questions/new
def new
#question = Question.new
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
def create
#question = Question.new(question_params)
#current_user ||= User.find_by_id(session[:user_id])
#question.update(:user_id => #current_user.id)
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
format.html { redirect_to questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :body)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#current_user ||= User.find_by_id(session[:user_id])
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
#current_user ||= User.find_by_id(session[:user_id])
#comment.update(:user_id => #current_user.id, :question_id => ?) # What to add here to get the specific question id?
respond_to do |format|
if #comment.save
format.html { redirect_to '/', notice: 'comment was successfully created.' }
format.json { render action: 'show', status: :created, location: #comment }
else
format.html { render action: 'new' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to '', notice: 'comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to '' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:title, :body)
end
end
index.html.erb
<h1>Listing questions</h1>
<%= link_to 'New Question', new_question_path %>
<hr>
<% #questions.each do |question| %>
<!-- Author -->
<%= question.user.name %> <br>
<!-- Date -->
<%= question.created_at %> <br>
<!-- Title -->
<%= question.title %> <br>
<!-- Body -->
<%= question.body %> <br>
<%= question.id %> <br>
<!-- Comment count -->
<%= question.comments.size %> Comment <br>
<!-- Comments -->
<% question.comments.each do |comment| %>
<!-- Comment Author -->
<%= comment.user.name %> <br>
<!-- Comment Date -->
<%= comment.created_at %> <br>
<!-- Comment Body -->
<%= comment.body %> <br>
<% end %>
<%= form_for(question.comments.new) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<hr>
<% end %>
Thank you in advance for your help! :)
The form_for will need to submit the question_id somehow - either by a route or through the form. I recommend a route.
If you don't interact with comments independently - if there is always a question, then change your routes to something like this:
resources :questions do
resources :comments
end
Then - in your form for, you will do this
<%= form_for [question, question.comments.new] do |f| %>
This will cause the form to submit (POST) to /question/:question_id/comments and you can handle it from there.
In the comments controller - you'll get the question from the params[:question_id] and return the result via an ajax response (respond to json).
This part is still tricky if you haven't done it before. If you need help with that part, you can probably find good examples or ask a separate question...
you can add hidden field inside your form
<%= f.hidden_field :question_id, value: question.id %>
or you can change your form
<%= form_for :comment, :url => comments_path(question_id:question.id) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
when u submit this form u will have url like /comments?question_id=id