bookings 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 89a350a55b9ba838cb16d342f701c7313febb6ce
4
+ data.tar.gz: ad559a94335c8169a500d421833cca42d8ed5b4d
5
+ SHA512:
6
+ metadata.gz: 800f05cf6bcf6ec779615c0f2be95a79b60f968396439d41a6b6bb20241633aa7c6b98af40f99fde9b6a058300efa4f602ce93752160e052e94e068665a8b6d1
7
+ data.tar.gz: 66a7187cb93626c6d9e6c9713e0e8032bf9c2ac9c11aa2bef4637a0da69a41c500aa48b4294bfda5aa33077120f78c354c3959aa70983a8042aec4fe8723138a
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bookings.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 V
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Bookings
2
+
3
+ Allow any model to take booking requests, and confirm them
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'bookings'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install bookings
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/bookings/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bookings/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bookings"
8
+ spec.version = Bookings::VERSION
9
+ spec.authors = ["Valentino Stoll"]
10
+ spec.email = ["thevalentino+code@gmail.com"]
11
+ spec.summary = %q{Allow any model to accept booking requests and confirmations.}
12
+ spec.description = %q{Allow any model to accept booking requests and confirmations.}
13
+ spec.homepage = "https://github.com/codenamev/bookings"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rails", "~> 4.1.4"
22
+ spec.add_dependency "aasm", "~> 3.2.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency('generator_spec')
26
+ spec.add_development_dependency "rake"
27
+ end
@@ -0,0 +1,16 @@
1
+ require "bookings/version"
2
+ require "bookings/railtie"
3
+
4
+ module Bookings
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def bookable
9
+ has_many :bookings, as: :bookable, dependent: :destroy
10
+
11
+ validates_associated :bookings
12
+ end
13
+ end
14
+ end
15
+
16
+ ActiveRecord::Base.send :include, Bookings if defined?(ActiveRecord::Base)
@@ -0,0 +1,12 @@
1
+ module Bookings
2
+ module Generators
3
+ class BookingModelGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def generate_bookings_model
7
+ copy_file "booking_model.rb", "app/models/booking.rb"
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Bookings
2
+ module Generators
3
+ class ControllerGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def generate_bookings_controller
7
+ template "bookings_controller.rb", "app/controllers/bookings_controller.rb"
8
+ route "resources :bookings"
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Bookings
2
+ module Generators
3
+ require 'rails/generators'
4
+
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../", __FILE__)
7
+
8
+ def install
9
+ generate "bookings:migration"
10
+ generate "bookings:booking_model"
11
+ generate "bookings:controller"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module Bookings
2
+ module Generators
3
+ require 'rails/generators/migration'
4
+
5
+ class MigrationGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ def self.next_migration_number(path)
10
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ end
12
+
13
+ def generate_bookings_migration
14
+ migration_template "bookings_migration.rb", "db/migrate/create_bookings.rb"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,68 @@
1
+ class Booking < ActiveRecord::Base
2
+ include AASM
3
+ belongs_to :bookable, polymorphic: true
4
+
5
+ validates :starts_at, presence: true
6
+ validate :starts_in_future
7
+ validate :timeslot_not_taken
8
+
9
+ aasm :column => 'booking_state', :whiny_transitions => false do
10
+ state :request, :initial => true
11
+ state :booked, :before_enter => :update_booked_at
12
+ state :cancelled, :before_enter => :update_cancelled_at
13
+ state :postponed
14
+
15
+ event :book, :after => Proc.new { perform_notification(:booked) } do
16
+ transitions :from => :request, :to => :booked
17
+ end
18
+
19
+ event :cancel, :after => Proc.new { perform_notification(:cancelled) } do
20
+ transitions :from => :booked, :to => :cancelled
21
+ end
22
+
23
+ event :postpone, :after => Proc.new { perform_notification(:postponed) } do
24
+ transitions :from => :booked, :to => :postponed
25
+ end
26
+ end
27
+
28
+ def self.current
29
+ where "starts_at >= ?", Date.today.beginning_of_day
30
+ end
31
+
32
+ def to_s
33
+ "#{self.name}"
34
+ end
35
+
36
+ private
37
+
38
+ def update_booked_at
39
+ self.booked_at = Time.now
40
+ end
41
+
42
+ def update_cancelled_at
43
+ self.cancelled_at = Time.now
44
+ end
45
+
46
+ def starts_in_future
47
+ if self.starts_at and self.starts_at < 15.minutes.from_now
48
+ errors.add(:starts_at, 'must be at least 15 minutes from now')
49
+ end
50
+ end
51
+
52
+ def timeslot_not_taken
53
+ table_name = self.class.table_name
54
+ if self.starts_at and self.ends_at
55
+ if self.class.where("#{table_name}.starts_at <= ? AND #{table_name}.ends_at IS NULL OR #{table_name}.ends_at >= ?", self.starts_at, self.ends_at).any?
56
+ errors.add(:base, "another #{self.class.to_s.downcase} has already been booked for the times you requested")
57
+ end
58
+ elsif self.starts_at
59
+ if self.class.where("#{table_name}.starts_at <= ?", self.starts_at).any?
60
+ errors.add(:base, "another #{self.class.to_s.downcase} has already been booked for the time you requested")
61
+ end
62
+ end
63
+ end
64
+
65
+ def perform_notification(notification_type)
66
+ ActiveSupport::Notifications.instrument("#{self.class.table_name.to_s.downcase}.#{notification_type}", :object => self)
67
+ end
68
+ end
@@ -0,0 +1,78 @@
1
+ class BookingsController < ApplicationController
2
+ respond_to :html, :json
3
+
4
+ before_action :find_booking, except: [:create, :index]
5
+
6
+ def index
7
+ @bookings = Booking.current.order(:starts_at)
8
+ respond_with @bookings
9
+ end
10
+
11
+ def new
12
+ @booking = Booking.new
13
+ end
14
+
15
+ def create
16
+ @booking = Booking.new(booking_params)
17
+
18
+ if @booking.save
19
+ if request.xhr?
20
+ render json: {status: :success}.to_json
21
+ else
22
+ redirect_to bookings_url
23
+ end
24
+ else
25
+ if request.xhr?
26
+ render json: {errors: @booking.errors.full_messages, status: :error}.to_json
27
+ else
28
+ render 'new'
29
+ end
30
+ end
31
+ end
32
+
33
+ def show
34
+ @booking = Booking.find(params[:id])
35
+ respond_with @bookings
36
+ end
37
+
38
+ def destroy
39
+ if @booking.destroy
40
+ flash[:notice] = "Booking: #{@booking} deleted"
41
+ redirect_to bookings_url
42
+ else
43
+ render 'index'
44
+ end
45
+ end
46
+
47
+ def edit
48
+ end
49
+
50
+ def update
51
+ if @booking.update(booking_params)
52
+ flash[:notice] = 'Your booking was updated successfully'
53
+
54
+ if request.xhr?
55
+ render json: {status: :success}.to_json
56
+ else
57
+ redirect_to bookings_url
58
+ end
59
+ else
60
+ if request.xhr?
61
+ render json: {errors: @booking.errors.full_messages, status: :error}.to_json
62
+ else
63
+ render 'edit'
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def booking_params
71
+ params[:booking].permit!
72
+ end
73
+
74
+ def find_booking
75
+ @booking = booking.find(params[:id])
76
+ end
77
+
78
+ end
@@ -0,0 +1,26 @@
1
+ class CreateBookings < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :bookings do |t|
4
+ t.column :bookable_id, :integer
5
+ t.column :bookable_type, :string
6
+ t.column :name, :string
7
+ t.column :summary, :text
8
+ t.column :terms, :text
9
+ t.column :starts_at, :datetime
10
+ t.column :ends_at, :datetime
11
+ t.column :booked_at, :datetime
12
+ t.column :cancelled_at, :datetime
13
+ t.column :paid_at, :datetime
14
+ t.column :payment_type, :string
15
+ t.column :requested_amount, :decimal
16
+ t.column :confirmed_amount, :decimal
17
+ t.column :booking_state, :string
18
+ end
19
+
20
+ add_index :bookings, [:bookable_id, :bookable_type]
21
+ end
22
+
23
+ def self.down
24
+ drop_table :bookings
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails/railtie'
2
+
3
+ module Bookings
4
+
5
+ class Railtie < Rails::Railtie
6
+ generators do
7
+ require "bookings/generators/booking_model_generator"
8
+ require "bookings/generators/controller_generator"
9
+ require "bookings/generators/migration_generator"
10
+ require "bookings/generators/install_generator"
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,3 @@
1
+ module Bookings
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'bookings/generators/install_generator'
3
+ require "generator_spec"
4
+
5
+ describe Bookings::Generators::InstallGenerator do
6
+ destination File.expand_path("../../../tmp", __FILE__)
7
+
8
+ before(:all) do
9
+ prepare_destination
10
+ run_generator
11
+ end
12
+
13
+ it "creates a migration file" do
14
+ assert_migration "db/migrations/create_bookings.rb"
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
5
+
6
+ $LOAD_PATH << File.join(ROOT, 'lib')
7
+ $LOAD_PATH << File.join(ROOT, 'lib', 'bookings')
8
+ require File.join(ROOT, 'lib', 'bookings.rb')
9
+
10
+ Dir[File.join(ROOT, 'spec', 'support', '**', '*.rb')].each{|f| require f }
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bookings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Valentino Stoll
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.1.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: aasm
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.2.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.2.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: generator_spec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Allow any model to accept booking requests and confirmations.
84
+ email:
85
+ - thevalentino+code@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - bookings.gemspec
96
+ - lib/bookings.rb
97
+ - lib/bookings/generators/booking_model_generator.rb
98
+ - lib/bookings/generators/controller_generator.rb
99
+ - lib/bookings/generators/install_generator.rb
100
+ - lib/bookings/generators/migration_generator.rb
101
+ - lib/bookings/generators/templates/booking_model.rb
102
+ - lib/bookings/generators/templates/bookings_controller.rb
103
+ - lib/bookings/generators/templates/bookings_migration.rb
104
+ - lib/bookings/railtie.rb
105
+ - lib/bookings/version.rb
106
+ - spec/lib/generators/install_generator_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: https://github.com/codenamev/bookings
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.2.2
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Allow any model to accept booking requests and confirmations.
132
+ test_files:
133
+ - spec/lib/generators/install_generator_spec.rb
134
+ - spec/spec_helper.rb