Trying to call save method from model - ruby-on-rails

I'm trying to update the number of holiday days an employee has when they book a holiday. I'm trying to save the employee from the model that doesn't seem to be working, the holiday creates perfectly otherwise. I had it working before but must've changed something by mistake as no matter what I do I cant get it back working. Any Ideas?
Holidays Controller
def create
#holiday = Holiday.new(holiday_params)
#holiday.employee_id = current_employee.id
if(Holiday.pastHol(#holiday))
if(Holiday.h_authorize(current_employee, #holiday))
if(Holiday.update_holidays(current_employee,#holiday))
respond_to do |format|
if #holiday.save
format.html { redirect_to action: "index", notice: 'holiday accecpted' }
format.json { render :show, status: :created, location: #holiday }
end
end
else
respond_to do |format|
format.html { redirect_to action: "index", notice: 'holiday declined' }
format.json { render json: #holiday.errors, status: :unprocessable_entity }
end
end
else
respond_to do |format|
format.html { redirect_to action: "index", notice: "Already on Hols" }
format.json { render json: #holiday.errors, status: :unprocessable_entity }
end
end
else
respond_to do |format|
format.html { redirect_to action: "index", notice: "Date error" }
format.json { render json: #holiday.errors, status: :unprocessable_entity }
end
end
end
Holiday Model
scope :update_holidays, lambda{ |q| where("amount > ?", q) }
scope :proj_authorize, lambda{ |q| where("amount > ?", q) }
def self.update_holidays(employee, holiday)
employee.DaysHolidays == employee.DaysHolidays - (holiday.endDate - holiday.startDate ) - 1
if (employee.DaysHolidays > 0)
employee.save
return true
else
return false
end
end
Holiday Index
<%= form_for(#holiday) do |f| %>
<%= errors_for(#holiday) %>
<h3>Holiday Request</h3>
<%= current_employee.name %> , you have <%= current_employee.DaysHolidays %> holiday days remaining.<br><br>
<p id="notice"><%= notice %></p>
<div class="field">
<%= f.label :startDate %><br>
<%= f.text_field :startDate , id: :datepicker, placeholder: "Start Date" %>
</div>
<div class="field">
<%= f.label :endDate %><br>
<%= f.text_field :endDate , id: :datepicker1, placeholder: "End Date" %>
<div class="actions">
<%= f.submit 'Request Holiday', :class => 'btn' %>
</div>
<% end %>
</form>
</div>

I've noticed that you've already found the answer to your question, but I really wanted to refactor a bit your controller. While I highly advise you move your if cases to a service class or underlying approach probably should be different but without other information, I can do so much. Here is a slight refactor while keeping everything in the controller:
def create
#holiday = Holiday.new(holiday_params)
#holiday.employee_id = current_employee.id
notice =
if(Holiday.pastHol(#holiday))
if(Holiday.h_authorize(current_employee, #holiday))
if(Holiday.update_holidays(current_employee, #holiday))
"holiday accepted"
else
"holiday declined"
end
else
"Already on Hols"
end
else
"Date error"
end
respond_to do |format|
format.html { redirect_to action: "index", notice }
if #holiday.save
format.json { render :show, status: :created, location: #holiday }
else
format.json { render json: #holiday.errors, status: :unprocessable_entity }
end
end
end

Related

I have the same form in two pages and i need to redirect to the same page of the form

My problem
I have two forms for one model on two different pages (opinions and user) when I click submit the form on the user page it redirects me to the opinions page, I know that I can redirect to the same page that I redirect in the action create but is there a way to redirect user form to the user page
User controller
class UsersController < ApplicationController
include TheUser
before_action :set_user
before_action :authenticate_user!
before_action :user_signed_in?
def index
#users = User.all
#mutual_friends = User.where(id: show_two_friends)
end
def show
#user = User.find(params[:id])
#new_opinion = Opinion.new
respond_to do |format|
if #user
format.html
format.js
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
format.js
end
end
end
private
def show_mutual_friends
#ids = []
current_user.friends.each do |person|
person.friends.each do |m|
#ids << m.id
end
end
#ids.reject { |x| x == current_user.id }
end
def show_two_friends
show_mutual_friends.sample(2)
end
end
Opinions controller
class OpinionsController < ApplicationController
include TheUser
before_action :set_user
before_action :set_opinion, only: [:show, :edit, :update, :destroy]
# GET /opinions
# GET /opinions.json
def index
#opinions = Opinion.all.order("created_at DESC")
#opinion = Opinion.new
end
# POST /opinions
# POST /opinions.json
def create
#opinion = #user.opinions.build(opinion_params)
respond_to do |format|
if #opinion.save
format.html { redirect_to opinions_url, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #opinion }
else
format.html { render :new }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /opinions/1
# PATCH/PUT /opinions/1.json
def update
respond_to do |format|
if #opinion.update(opinion_params)
format.html { redirect_to #opinion, notice: 'Opinion was successfully updated.' }
format.json { render :show, status: :ok, location: #opinion }
else
format.html { render :edit }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
# DELETE /opinions/1
# DELETE /opinions/1.json
def destroy
#opinion.destroy
respond_to do |format|
format.html { redirect_to opinions_url, notice: 'Opinion was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_opinion
#opinion = Opinion.find(params[:id])
end
# Only allow a list of trusted parameters through.
def opinion_params
params.require(:opinion).permit(:user, :body, :user_id)
end
end
User form
<%= form_with(model: #new_opinion, local: false) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= form.button :submit %>
<% end %>
Opinions form
<%= form_with(model: #opinion, local: true) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= form.button :submit, class: "button is-info" %>
<% end %>
I will really appreciate it if you guys help me with this it's my final project
The solution is by adding a hiddin_field_tag and redirect each form to the desired path like this:
<%= form_with(model: #new_opinion, local: true) do |form| %>
<div class="field rich p-3">
<div class="control">
<%= form.rich_text_area :body, label: "What's Your Opinion", input_html: {class: "textarea"}, wrapper: false, label_html: {class: "label"}, placeholders: "Your opinion...", autofocus: true %>
</div>
</div>
<%= hidden_field_tag(:redirect_url, user_path(#user.id)) %>
<%= form.button :submit %>
<% end %>
And redirect the create action in the controller to the params
def create
#opinion = #user.opinions.build(opinion_params)
respond_to do |format|
if #opinion.save
format.html { redirect_to(params[:redirect_url]) }
format.json { render :show, status: :created, location: #opinion }
else
format.html { render :new }
format.json { render json: #opinion.errors, status: :unprocessable_entity }
end
end
end
Rails 5 has redirect_back
& Then change
redirect_to opinions_url
to
redirect_back(fallback_location: root_path)

Getting a "NoMethodError in Boards#show" error when going to #new action (not trying to access a method, and the variable exists)

I'm very new to Ruby on Rails, so forgive if this is a stupid mistake.
I used a rails generate scaffold command to generate a "board" scaffold with a title:string and message:text. Now, I'm trying to go to localhost:3000/boards/new and I'm getting a "NoMethodError in Boards#show" error when I try to access board.message. I don't get any error when I try to access board.title.
Code:
form.html.erb
<%= form_for(#board) do |f| %>
<% if #board.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#board.errors.count, "error") %> prohibited this board from being saved:</h2>
<ul>
<% #board.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 :message %><br />
<%= f.text_area :message %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm specifically getting the error on line 20 (<%= f.text_area :message %>)
board.rb
class Board < ActiveRecord::Base
attr_accessible :message, :title
has_many :posts
end
*boards_controller.rb*
class BoardsController < ApplicationController
# GET /boards
# GET /boards.json
def index
#boards = Board.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #boards }
end
end
# GET /boards/1
# GET /boards/1.json
def show
#board = Board.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #board }
end
end
# GET /boards/new
# GET /boards/new.json
def new
#board = Board.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
# GET /boards/1/edit
def edit
#board = Board.find(params[:id])
end
# POST /boards
# POST /boards.json
def create
#board = Board.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# PUT /boards/1
# PUT /boards/1.json
def update
#board = Board.find(params[:id])
respond_to do |format|
if #board.update_attributes(params[:board])
format.html { redirect_to #board, notice: 'Board was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# DELETE /boards/1
# DELETE /boards/1.json
def destroy
#board = Board.find(params[:id])
#board.destroy
respond_to do |format|
format.html { redirect_to boards_url }
format.json { head :no_content }
end
end
end
routes.rb
Anonymous::Application.routes.draw do
resources :boards
resources :posts
root :to => "boards#index"
end
Can anyone please explain this to me?

Rails trying to save form with collection_select that is empty gives undefined method `map' for nil:NilClass

I have a form with a drop down generated from a collection_select. The collection_select starts off blank and then when the user selects a date from the date field, the collection_select is updated with values for the date that is chosen.
I'm trying to show a nice error message if the form is submitted without a value chosen in my dropdown. Currently i'm getting this error: undefined methodmap' for nil:NilClass`
How can i make it so that if the user doesn't select a value in the dropdown, I can show them a nice error message?
View
<%= form_for(#arrangement) do |f| %>
<div class="control-group">
<%= f.label :date, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :date, :class => 'input-large datepicker' %>
</div>
</div>
<div class="control-group">
<%= f.label :timeslot, :class => 'control-label' %>
<div class="controls">
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
</div>
</div>
<% end %>
Controller
# GET /arrangements/new
# GET /arrangements/new.json
def new
date = Time.now.to_date.to_s(:db)
#arrangement = Arrangement.new
#available_timeslots = Timeslot.where("location_id = ? AND date(timeslot) = ? AND arrangement_id is null", current_user.user_details.location_id, date).order('timeslot ASC')
respond_to do |format|
format.html # new.html.erb
format.json { render json: #arrangement }
end
end
# POST /arrangements
# POST /arrangements.json
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end
The error given is referring to #available_timeslots being empty when trying to save the form
I would try something like this.
def new
#available_timeslots = ...
if #available_timeslots.count > 0
flash.now[:error] = "nil errrraaarrr"
end
...
end
In view
<div class="controls">
<%- if #available_timeslots.count > 0 %>
<%= collection_select(:arrangement, :timeslot_id, #available_timeslots, :id, :timeslot_spelled) %>
<% else %>
<%= flash.now[:error] %>
<% end %>
</div>
#available_timeslots is nil. Make sure it's set with an array of available timeslots to avoid this error message.
The trick was to add #available_timeslots = [] in the else clause
def create
#arrangement = Arrangement.new(params[:arrangement])
respond_to do |format|
if #arrangement.save
# update the timslot record with the arrangement id
if #timeslot = Timeslot.update(#arrangement.timeslot_id, :arrangement_id => #arrangement.id)
format.html { redirect_to #arrangement, notice: 'Arrangement was successfully created.' }
format.json { render json: #arrangement, status: :created, location: #arrangement }
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #arrangement.errors, status: :unprocessable_entity }
end
end
end

Assigning multiple associations with Simple_form

I understand how to implement a single has_many association using simple_form, but how do you assign an additional association from another model object?
In my code, I'm creating model object #opportunity. I'm currently assigning a company_id, but also need to assign a 'user_id.
#opportunity _form.html.erb
<% if user_signed_in? %>
<%= simple_form_for([#company, #company.opportunities.build], html: {class: "form-inline"}) do |f| %>
<%= f.error_notification %>
<%= f.input :description, label: false, placeholder: 'Create an opportunity', input_html: { class: "span4" } %>
<%= f.submit 'Submit', class: 'btn btn-small'%>
<% end %>
<% else %>
<%= link_to "Create an Account", new_user_registration_path %>
to contribute
<% end %>
opportunity_controller.rb
def create
#company = Company.find(params[:company_id])
#opportunity = #company.opportunities.create(params[:opportunity])
respond_to do |format|
if #opportunity.save
format.html { redirect_to company_path(#company), notice: 'Opportunity was successfully created.' }
format.json { render json: #opportunity, status: :created, location: #opportunity }
else
format.html { render action: "new" }
format.json { render json: #opportunity.errors, status: :unprocessable_entity }
end
end
end
Assuming that your user is logged in, you can change your controller action to the following:
def create
#company = Company.find(params[:company_id])
#opportunity = #company.opportunities.new(params[:opportunity]) # new instead of create
#opportunity.user = current_user # new
respond_to do |format|
if #opportunity.save
format.html { redirect_to company_path(#company), notice: 'Opportunity was successfully created.' }
format.json { render json: #opportunity, status: :created, location: #opportunity }
else
format.html { render action: "new" }
format.json { render json: #opportunity.errors, status: :unprocessable_entity }
end
end
end

redirect using a form

this form (views/workers/_form.html.erb) redirects me to the index of tasksadmins, after I push the 'create tasksadmin' button.
I want it to redirect me to "workers/index" and change the button to 'update the task'.
how can I do that please?
<%= form_for(#tasksadmin) do |f| %>
<% if #tasksadmin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#tasksadmin.errors.count, "error") %> prohibited this tasksadmin from being saved:</h2>
<ul>
<% #tasksadmin.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :admin_mail, :value => #tasksadmin.admin_mail %>
<%= f.hidden_field :worker_mail, :value => #worker_mail %>
<%= f.hidden_field :task, :value => #tasksadmin.task %>
<div class="field">
<%= f.label :done %><br />
<%= f.check_box :done %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and this is my workers_controller:
class WorkersController < ApplicationController
# GET /workers
# GET /workers.json
def index
#tasks_worker = Tasksadmin.where(:worker_mail => "alon.shmiel#gmail.com")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #workers }
end
end
# GET /workers/1
# GET /workers/1.json
def show
#task_worker = Tasksadmin.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #worker }
end
end
# GET /workers/new
# GET /workers/new.json
def new
#worker = Worker.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #worker }
end
end
# GET /workers/1/edit
def edit
#tasksadmin = Tasksadmin.find(params[:id])
#worker_mail = "alon.shmiel#gmail.com"
end
# POST /workers
# POST /workers.json
def create
#worker = Worker.new(params[:worker])
respond_to do |format|
if #worker.save
format.html { redirect_to "#worker", notice: 'Worker was successfully created.' }
format.json { render json: #worker, status: :created, location: #worker }
else
format.html { render action: "new" }
format.json { render json: #worker.errors, status: :unprocessable_entity }
end
end
end
# PUT /workers/1
# PUT /workers/1.json
def update
#worker = Tasksadmin.find(params[:id])
respond_to do |format|
if #worker.update_attributes(params[:worker])
format.html { render action: "index", notice: 'Worker was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #worker.errors, status: :unprocessable_entity }
end
end
end
# DELETE /workers/1
# DELETE /workers/1.json
def destroy
#worker = Tasksadmin.find(params[:id])
#worker.destroy
respond_to do |format|
format.html { render action: "index" }
format.json { render json: #worker }
end
end
end
In your controller, you have to redirect to the appropriate path like so:
def update
redirect_to "workers/index"
end
I would suggest using path helpers so if you have your routes set up as resources, you can do this:
redirect_to workers_path
As for changing the the button text, just change it to:
f.submit("update the task")
You create a form for an object #tasksadmin, which in your WorkersController#edit is set as follows:
#tasksadmin = Tasksadmin.find(params[:id]
This means that that parameter contains an object of class Tasksadmin, if you let rails build the path for the a Tasksadmin, it will send you to the TasksadminsController#update, and that is why your code does not work. You never get to the WorkersController#update. Check your logs to verify that.
Let me be very clear about this: you should not edit Tasksadmin objects in the WorkersController.
I do not understand why you would do that.

Resources