Forum: Ruby on Rails not saving to database (save unless)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
430bc35a253616d67e2c37b19820a9e2?d=identicon&s=25 Ruth Stephenson (bruceinjapan)
on 2016-06-30 16:27
Hi, I have a very beginners understanding of rails and ruby and I keep
getting stuck. Some previous posts have helped me a great deal but I now
have a different issue and so I thought I should start another post with
a different topic.

I am making an appointment booking app and I have a very basic design. I
have created an appointments scaffold with name:string phone:string
email:string numpeople:integer date:date timeslot:string. On the view
for creating a new appointment I have stated that appointment 1 is
9-11am, appointment 2 is 12-2pm, appointment 3 is 3-5pm and appointment
4 is 5 - 7pm. The user is asked to enter 1,2,3 or 4.

When the user clicks on "make appointment" I'm trying to interrupt the
appointments controller (create method)  so that I can check if the date
&& timeslot are nil. if that is the case, the system should continue on
to create the appointment, if not then I want to redirect to somewhere
else. I have created a method called isValid? in the model (See below)

I think the method is correct as the system is getting as far as the
redirect. The problem is, it keeps redirecting to the page I told it to
go to if it's not saved(the homepage or root_path). (Also the
appointments are not saving).

So, there now seems to be an issue with saving the appointment data to
the database.

If anyone could give me some pointers, I would be so, so grateful!

CODE:

appointments Model:
class Appointment < ActiveRecord::Base

  def isValid?
    taken= Appointment.where("date = ? && timeslot = ?", date,timeslot)
     Appointment.save unless taken
  end
end


appointments controller:

def create
    valid = @appointment = Appointment.new(appointment_params).isValid?

      respond_to do |format|
      if valid
        format.html { redirect_to new_appointment_path, notice:
'Appointment was successfully created.' }
        format.json { render :show, status: :created, location:
@appointment }
      else
        format.html { redirect_to root_path, notice: 'That appointment
is not available, please choose again' } # this redirect works with no
notice
        format.js { render json: @appointment.errors, status:
:unprocessable_entity }
      end
    end
  end
4c6bde00168d595053c09aac7e487f8e?d=identicon&s=25 Colin Law (Guest)
on 2016-06-30 16:36
(Received via mailing list)
On 30 June 2016 at 15:27, Ruth Stephenson <lists@ruby-forum.com> wrote:
> 4 is 5 - 7pm. The user is asked to enter 1,2,3 or 4.
>
> When the user clicks on "make appointment" I'm trying to interrupt the
> appointments controller (create method)  so that I can check if the date
> && timeslot are nil. if that is the case, the system should continue on
> to create the appointment, if not then I want to redirect to somewhere
> else. I have created a method called isValid? in the model (See below)

You should probably be using rails validations for this, most of the
work will then be done for you by rails.  I suggest that you work
right through a good tutorial such as railstutorial.org, which will
show you the basics of rails and save both yourself and us a lot of
time in the long run.  To get a flavour of validations you can look at
the Rails Guide on ActiveRecord Validations.

Colin
684b64cf1db4f88d642531024278ec40?d=identicon&s=25 Radhames Brito (rbritom)
on 2016-06-30 17:41
(Received via mailing list)
I think I understand what you want now, this is a clean up of what you
did
but I dont think is what you want

def create
  @appointment = Appointment.where("date = ? && timeslot = ?",
date,timeslot).first_or_initialize

  respond_to do |format|
    if @appointment.new_record? # this means you did NOT found an
Appointment for the given date and timeslot
      format.html { redirect_to new_appointment_path, notice:
'Appointment was successfully created.' }
      format.json { render :show, status: :created, location:
@appointment }
    else # this means you did found an Appointment for the given date
and
timeslot
      format.html { redirect_to root_path, notice: 'That appointment
is not available, please choose again' } # this redirect works with no
notice
      format.js { render json: @appointment.errors, status:
:unprocessable_entity }
    end
  end
end

 now keep in mind that you are doing it wrong, 'create action' it for
creating, what you need is
 a contitional link that leads to either new or index action and leave
create alone doing only what
 it should. So can you explain your goal as a user story, so that I can
guide you to do it properly ?


On Thu, Jun 30, 2016 at 10:27 AM, Ruth Stephenson <lists@ruby-forum.com>
430bc35a253616d67e2c37b19820a9e2?d=identicon&s=25 Ruth Stephenson (bruceinjapan)
on 2016-06-30 17:56
Hi rbritom, I really appreciate your help on this!

I guess my goal (as a user story) is:

I want to be able to make an appointment that has not already been made.
I don't want to have double (or worse!) booked appointments. I want to
be able to check the appointments table and make the booking if that
date and timeslot has not been taken already. If it has, I want the
system to save my appointment and display a notice to me to say that the
booking was made successfully. If the date and time selected are not
available then I want it to tell me it's not available and to try again.

When I get that working, I want to add an action_mailer to send the
customer an email with the booking details, and I also want it send me
an email with the booking details.
430bc35a253616d67e2c37b19820a9e2?d=identicon&s=25 Ruth Stephenson (bruceinjapan)
on 2016-06-30 18:32
I'm actually still a little confused..

Where is the save? As my save unless taken in the model doesn't work
430bc35a253616d67e2c37b19820a9e2?d=identicon&s=25 Ruth Stephenson (bruceinjapan)
on 2016-06-30 18:35
This solution gives an error:
undefined local variable or method `date' for #<AppointmentsController:

@appointment = Appointment.where("date = ? && timeslot = ?", date,
timeslot).first_or_initialize

Basically, I want to not create double appointments for the same date
and time, and I want to save them if they're not double bookings.

There must be an easier way??
Bee69cfed999cd13e3bff73d472a39ee?d=identicon&s=25 Hassan Schroeder (Guest)
on 2016-06-30 19:22
(Received via mailing list)
On Thu, Jun 30, 2016 at 9:35 AM, Ruth Stephenson <lists@ruby-forum.com>
wrote:

> Basically, I want to not create double appointments for the same date
> and time, and I want to save them if they're not double bookings.
>
> There must be an easier way??

There is - take Colin's advice about working through a tutorial and
learn, for this use case at least, about ActiveRecord validations...

--
Hassan Schroeder ------------------------ hassan.schroeder@gmail.com
http://about.me/hassanschroeder
twitter: @hassan
Consulting Availability : Silicon Valley or remote
684b64cf1db4f88d642531024278ec40?d=identicon&s=25 Radhames Brito (rbritom)
on 2016-06-30 19:26
(Received via mailing list)
thanks, ill send you back an answer in a bit, ill try to add as much
comments are possible

On Thu, Jun 30, 2016 at 11:56 AM, Ruth Stephenson <lists@ruby-forum.com>
684b64cf1db4f88d642531024278ec40?d=identicon&s=25 Radhames Brito (rbritom)
on 2016-06-30 20:00
(Received via mailing list)
I have omitted some of the code for brevity

# controller
class AppointmentsController < ApplicationController
  def index
    @appointments = Appointment.all
  end

  def new
    @appointment = Appointment.find(params[:id])
  end

  def create
    @appointment = Appointment.new(appointment_params)

    respond_to do |format|
      if @appointment.save # here is your save
        format.html { redirect_to appointments_path, notice:
'Appointment
created successfuly' }
        format.js   {...} # put your code here
      else
        format.html { render :new }
        format.js   {...}
      end
    end
  end

  # rest of your code below
end

# Model
class Appointment < ActiveRecord::Base
  # this is what the guys meant by "move this to active record
validation"
  validates :date, uniqueness: { scope: :timeslot } # this will return a
validation error if an appointment exist with the same date and timeslot
end


Now in the view, the index page should have a table with dates and
timeslots have a look at this railscast to learn how to do that, but
note
that the railscast it pretty old,
http://railscasts.com/episodes/213-calendars, still it will help you to
create a calendar, im pretty sure there is also a gem that can do it for
you, but if you are learning the railscast will help you a lot. Then
there,
there should be create appointment link inside the free times slot, and
then the appointment title in the timeslots that are already in use, its
all most about the presentation of the index and the calendar, there not
much logic inside create action besides what I have posted here. Dont be
afraid to keep asking, and go into railscast and browse around there are
some pretty good ones there that can help you learn the basics easily.

http://railscasts.com/


On Thu, Jun 30, 2016 at 10:27 AM, Ruth Stephenson <lists@ruby-forum.com>
430bc35a253616d67e2c37b19820a9e2?d=identicon&s=25 Ruth Stephenson (bruceinjapan)
on 2016-07-01 13:14
Thank you very much! I am now reading about Active Record Validations
and it's making a lot more sense to me and your solution also makes
sense to me now. I am learning! I really appreciate your help.
This topic is locked and can not be replied to.