Cross Gozon Cross Gozon - 6 months ago 15
Ruby Question

If selection = ?..then, how to decrease the a value of an integer attribute?

i am working with a reservation system and i am having problem with the constraints.. i have a list of cottages with a number of cottages vacant.. a working sytem i swhen the customer reserve a cottage the number of vacant cottage need to decrease.. please help me i have here some codes i started... and an image to help you understand my explanation..

what i want to accomplish here is:

Before a reservation: Cottage Availability: 5

if i fill up information & select "small cottage" and create reservation the availability value will -1.

After a reservation: Cottage availability: 4

form.html.erb

<%= form_for(@reservation) do |f| %>

<%= f.label :reservation_date %><br>
<%= f.date_select :reservation_date %>

<%= f.label :customer_name %><br>
<%= f.text_field :customer_name %>

<%= f.label :address%><br>
<%= f.text_field :address %>

<%= f.label :contact_no %><br>
<%= f.text_field :contact_no %>

<%= f.label :cottage_class %><br>
<%= f.select :cottage_id, options_for_select( Cottage.all.map { |g| [g.name, g.id]}) %>

<%= f.submit %>
<% end %>


schema.rb

ActiveRecord::Schema.define(version: 20160514141006) do

create_table "cottages", force: :cascade do |t|
t.string "name"
t.string "rates"
t.integer "no_of_vacant_cottage"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "reservations", force: :cascade do |t|
t.date "reservation_date"
t.string "customer_name"
t.string "address"
t.string "contact_no"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cottage_id"
end

add_index "reservations", ["cottage_id"], name: "index_reservations_on_cottage_id"

end


reservation.rb

class Reservation < ActiveRecord::Base
validates :customer_name, :presence => true
validates :address, :presence => true
validates :contact_no, :presence => true

belongs_to :cottage
end


cottage.rb

class Cottage < ActiveRecord::Base
has_many :reservations
end


Form and list of cottages existing on the database

Answer

I don't necessarily see the point of what you try to do, but still I'll try to answer your specific problen.

First, we want to initialize the number of vacant cottages to 5, for this when you create the table you can put :

create_table "cottages", force: :cascade do |t|
  # ...
  t.integer  "no_of_vacant_cottage", default: 5
  #...
end

Or if you cannot directly change your migration you could make a migration especially for that :

change_column :cottages, :no_of_vacant_cottage, :integer, :default => 5

Okay, so now our no_of_vacant_cottage column is by default set to 5. Now, whenever you make a new reservation you want to decrease the corresponding cottage's no_of_vacant_cottage column by 1. You can use a callback for that. What you probably want here is after_save.

So in your reservation model you will have something that looks like this:

class Reservation < ActiveRecord::Base
  validates :customer_name, :presence => true
  validates :address, :presence => true
  validates :contact_no, :presence => true
  belongs_to :cottage

  after_save :decrement_no_of_vacant_cottage

  def decrement_no_of_vacant_cottage
    c = self.cottage
    c.update(no_of_vacant_cottage: c.no_of_vacant_cottage -1)
  end
end

Please note that it will do this every time the reservation is saved and that even if you change the cottage_id of your reservation the old cottage will still keep his "-1". I let you handle those cases now that you know what callbacks are.