twilio-rails 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE +21 -0
- data/README.md +413 -0
- data/Rakefile +8 -0
- data/app/assets/config/twilio_rails_manifest.js +1 -0
- data/app/assets/stylesheets/twilio/rails/application.css +15 -0
- data/app/controllers/twilio/rails/application_controller.rb +6 -0
- data/app/controllers/twilio/rails/phone_controller.rb +112 -0
- data/app/controllers/twilio/rails/sms_controller.rb +64 -0
- data/app/helpers/twilio/rails/application_helper.rb +6 -0
- data/app/jobs/twilio/rails/application_job.rb +6 -0
- data/app/jobs/twilio/rails/phone/attach_recording_job.rb +15 -0
- data/app/jobs/twilio/rails/phone/finished_call_job.rb +15 -0
- data/app/jobs/twilio/rails/phone/unanswered_call_job.rb +15 -0
- data/app/mailers/twilio/rails/application_mailer.rb +8 -0
- data/app/models/twilio/rails/application_record.rb +7 -0
- data/app/operations/twilio/rails/application_operation.rb +21 -0
- data/app/operations/twilio/rails/find_or_create_phone_caller_operation.rb +29 -0
- data/app/operations/twilio/rails/phone/attach_recording_operation.rb +31 -0
- data/app/operations/twilio/rails/phone/base_operation.rb +21 -0
- data/app/operations/twilio/rails/phone/create_operation.rb +49 -0
- data/app/operations/twilio/rails/phone/find_operation.rb +14 -0
- data/app/operations/twilio/rails/phone/finished_call_operation.rb +17 -0
- data/app/operations/twilio/rails/phone/receive_recording_operation.rb +35 -0
- data/app/operations/twilio/rails/phone/start_call_operation.rb +53 -0
- data/app/operations/twilio/rails/phone/twiml/after_operation.rb +37 -0
- data/app/operations/twilio/rails/phone/twiml/base_operation.rb +50 -0
- data/app/operations/twilio/rails/phone/twiml/error_operation.rb +22 -0
- data/app/operations/twilio/rails/phone/twiml/greeting_operation.rb +22 -0
- data/app/operations/twilio/rails/phone/twiml/prompt_operation.rb +109 -0
- data/app/operations/twilio/rails/phone/twiml/prompt_response_operation.rb +29 -0
- data/app/operations/twilio/rails/phone/twiml/request_validation_failure_operation.rb +16 -0
- data/app/operations/twilio/rails/phone/twiml/timeout_operation.rb +48 -0
- data/app/operations/twilio/rails/phone/unanswered_call_operation.rb +22 -0
- data/app/operations/twilio/rails/phone/update_operation.rb +26 -0
- data/app/operations/twilio/rails/phone/update_response_operation.rb +38 -0
- data/app/operations/twilio/rails/sms/base_operation.rb +17 -0
- data/app/operations/twilio/rails/sms/create_operation.rb +23 -0
- data/app/operations/twilio/rails/sms/find_message_operation.rb +15 -0
- data/app/operations/twilio/rails/sms/find_operation.rb +15 -0
- data/app/operations/twilio/rails/sms/send_operation.rb +102 -0
- data/app/operations/twilio/rails/sms/twiml/base_operation.rb +11 -0
- data/app/operations/twilio/rails/sms/twiml/error_operation.rb +15 -0
- data/app/operations/twilio/rails/sms/twiml/message_operation.rb +49 -0
- data/app/operations/twilio/rails/sms/update_message_operation.rb +27 -0
- data/app/views/layouts/twilio/rails/application.html.erb +15 -0
- data/config/routes.rb +16 -0
- data/lib/generators/twilio/rails/install/USAGE +15 -0
- data/lib/generators/twilio/rails/install/install_generator.rb +34 -0
- data/lib/generators/twilio/rails/install/templates/initializer.rb +83 -0
- data/lib/generators/twilio/rails/install/templates/message.rb +4 -0
- data/lib/generators/twilio/rails/install/templates/migration.rb +89 -0
- data/lib/generators/twilio/rails/install/templates/phone_call.rb +4 -0
- data/lib/generators/twilio/rails/install/templates/phone_caller.rb +4 -0
- data/lib/generators/twilio/rails/install/templates/recording.rb +4 -0
- data/lib/generators/twilio/rails/install/templates/response.rb +4 -0
- data/lib/generators/twilio/rails/install/templates/sms_conversation.rb +4 -0
- data/lib/generators/twilio/rails/phone_tree/USAGE +8 -0
- data/lib/generators/twilio/rails/phone_tree/phone_tree_generator.rb +12 -0
- data/lib/generators/twilio/rails/phone_tree/templates/tree.rb.erb +13 -0
- data/lib/generators/twilio/rails/sms_responder/USAGE +8 -0
- data/lib/generators/twilio/rails/sms_responder/sms_responder_generator.rb +12 -0
- data/lib/generators/twilio/rails/sms_responder/templates/responder.rb.erb +10 -0
- data/lib/tasks/rails_tasks.rake +45 -0
- data/lib/twilio/rails/client.rb +75 -0
- data/lib/twilio/rails/concerns/has_direction.rb +25 -0
- data/lib/twilio/rails/concerns/has_phone_number.rb +27 -0
- data/lib/twilio/rails/concerns/has_time_scopes.rb +19 -0
- data/lib/twilio/rails/configuration.rb +380 -0
- data/lib/twilio/rails/engine.rb +11 -0
- data/lib/twilio/rails/formatter.rb +93 -0
- data/lib/twilio/rails/models/message.rb +21 -0
- data/lib/twilio/rails/models/phone_call.rb +132 -0
- data/lib/twilio/rails/models/phone_caller.rb +100 -0
- data/lib/twilio/rails/models/recording.rb +27 -0
- data/lib/twilio/rails/models/response.rb +153 -0
- data/lib/twilio/rails/models/sms_conversation.rb +29 -0
- data/lib/twilio/rails/phone/base_tree.rb +229 -0
- data/lib/twilio/rails/phone/tree.rb +229 -0
- data/lib/twilio/rails/phone/tree_macros.rb +147 -0
- data/lib/twilio/rails/phone.rb +12 -0
- data/lib/twilio/rails/phone_number.rb +29 -0
- data/lib/twilio/rails/railtie.rb +17 -0
- data/lib/twilio/rails/sms/delegated_responder.rb +97 -0
- data/lib/twilio/rails/sms/responder.rb +33 -0
- data/lib/twilio/rails/sms.rb +12 -0
- data/lib/twilio/rails/version.rb +5 -0
- data/lib/twilio/rails.rb +89 -0
- metadata +289 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
class InstallTwilioRails < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table "messages", force: :cascade do |t|
|
4
|
+
t.bigint "sms_conversation_id", null: false
|
5
|
+
t.string "sid"
|
6
|
+
t.text "body"
|
7
|
+
t.string "status"
|
8
|
+
t.string "direction"
|
9
|
+
t.datetime "created_at", null: false
|
10
|
+
t.datetime "updated_at", null: false
|
11
|
+
t.index ["created_at"], name: "index_messages_on_created_at"
|
12
|
+
t.index ["direction"], name: "index_messages_on_direction"
|
13
|
+
t.index ["sms_conversation_id"], name: "index_messages_on_sms_conversation_id"
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table "phone_callers", force: :cascade do |t|
|
17
|
+
t.string "phone_number"
|
18
|
+
t.datetime "created_at", null: false
|
19
|
+
t.datetime "updated_at", null: false
|
20
|
+
t.index ["phone_number"], name: "index_phone_callers_on_phone_number"
|
21
|
+
end
|
22
|
+
|
23
|
+
create_table "phone_calls", force: :cascade do |t|
|
24
|
+
t.integer "phone_caller_id"
|
25
|
+
t.string "sid"
|
26
|
+
t.string "number"
|
27
|
+
t.string "from_number"
|
28
|
+
t.string "from_city"
|
29
|
+
t.string "from_province"
|
30
|
+
t.string "from_country"
|
31
|
+
t.string "tree_name"
|
32
|
+
t.string "direction"
|
33
|
+
t.string "answered_by"
|
34
|
+
t.boolean "unanswered", default: false
|
35
|
+
t.boolean "finished", default: false
|
36
|
+
t.string "call_status"
|
37
|
+
t.integer "length_seconds"
|
38
|
+
t.datetime "created_at", null: false
|
39
|
+
t.datetime "updated_at", null: false
|
40
|
+
t.index ["created_at"], name: "index_phone_calls_on_created_at"
|
41
|
+
t.index ["direction"], name: "index_phone_calls_on_direction"
|
42
|
+
t.index ["phone_caller_id"], name: "index_phone_calls_on_phone_caller_id"
|
43
|
+
t.index ["sid"], name: "index_calls_on_sid"
|
44
|
+
t.index ["tree_name"], name: "index_phone_calls_on_tree_name"
|
45
|
+
end
|
46
|
+
|
47
|
+
create_table "recordings", force: :cascade do |t|
|
48
|
+
t.bigint "phone_call_id", null: false
|
49
|
+
t.string "recording_sid"
|
50
|
+
t.string "duration"
|
51
|
+
t.string "url"
|
52
|
+
t.datetime "created_at", null: false
|
53
|
+
t.datetime "updated_at", null: false
|
54
|
+
t.index ["phone_call_id"], name: "index_recordings_on_call_id"
|
55
|
+
end
|
56
|
+
|
57
|
+
create_table "responses", force: :cascade do |t|
|
58
|
+
t.bigint "phone_call_id"
|
59
|
+
t.bigint "recording_id"
|
60
|
+
t.string "prompt_handle"
|
61
|
+
t.string "digits"
|
62
|
+
t.text "transcription"
|
63
|
+
t.boolean "transcribed", default: false
|
64
|
+
t.boolean "timeout", default: false
|
65
|
+
t.datetime "created_at", null: false
|
66
|
+
t.datetime "updated_at", null: false
|
67
|
+
t.index ["created_at"], name: "index_responses_on_created_at"
|
68
|
+
t.index ["digits"], name: "index_responses_on_digits"
|
69
|
+
t.index ["phone_call_id", "prompt_handle"], name: "index_responses_on_phone_call_id_and_prompt_handle"
|
70
|
+
t.index ["prompt_handle"], name: "index_responses_on_prompt_handle"
|
71
|
+
t.index ["recording_id"], name: "index_responses_on_recording_id"
|
72
|
+
t.index ["timeout"], name: "index_responses_on_timeout"
|
73
|
+
t.index ["transcribed"], name: "index_responses_on_transcribed"
|
74
|
+
end
|
75
|
+
|
76
|
+
create_table "sms_conversations", force: :cascade do |t|
|
77
|
+
t.string "number"
|
78
|
+
t.string "from_number"
|
79
|
+
t.string "from_city"
|
80
|
+
t.string "from_province"
|
81
|
+
t.string "from_country"
|
82
|
+
t.datetime "created_at", null: false
|
83
|
+
t.datetime "updated_at", null: false
|
84
|
+
t.index ["created_at"], name: "index_sms_conversations_on_created_at"
|
85
|
+
t.index ["from_number"], name: "index_sms_conversations_on_from_number"
|
86
|
+
t.index ["number"], name: "index_sms_conversations_on_number"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class Twilio::Rails::PhoneTreeGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path("templates", __dir__)
|
4
|
+
|
5
|
+
def copy_template_tree
|
6
|
+
template "tree.rb.erb", "app/phone_trees/#{file_name}_tree.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
def register_tree
|
10
|
+
insert_into_file "config/initializers/twilio_rails.rb", "\n config.phone_trees.register { #{class_name}Tree }", before: "\nend\n"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class <%= class_name %>Tree < Twilio::Rails::Phone::BaseTree
|
3
|
+
# voice "male"
|
4
|
+
# final_timeout_message("Goodbye.")
|
5
|
+
# invalid_phone_number("Sorry, we cannot accept your call.")
|
6
|
+
|
7
|
+
greeting message: "Hello!",
|
8
|
+
prompt: :thanks_and_hangup
|
9
|
+
|
10
|
+
prompt :thanks_and_hangup,
|
11
|
+
message: "Thank you for calling!",
|
12
|
+
after: { hangup: true }
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class Twilio::Rails::SmsResponderGenerator < Rails::Generators::NamedBase
|
3
|
+
source_root File.expand_path("templates", __dir__)
|
4
|
+
|
5
|
+
def copy_template_responder
|
6
|
+
template "responder.rb.erb", "app/sms_responders/#{file_name}_responder.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
def register_responder
|
10
|
+
insert_into_file "config/initializers/twilio_rails.rb", "\n config.sms_responders.register { #{class_name}Responder }", before: "\nend\n"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class <%= class_name %>Responder < Twilio::Rails::SMS::DelegatedResponder
|
3
|
+
def handle?
|
4
|
+
raise NotImplementedError, "Implement #{ self.class }#handle?"
|
5
|
+
end
|
6
|
+
|
7
|
+
def reply
|
8
|
+
raise NotImplementedError, "Implement #{ self.class }#reply"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
namespace :twilio do
|
3
|
+
namespace :rails do
|
4
|
+
desc "Show the available values to config in Twilio"
|
5
|
+
task config: :environment do
|
6
|
+
if Twilio::Rails.config.host.blank?
|
7
|
+
puts "Twilio::Rails.config.host is not set. Set it in the `config/initializers/twilio_rails.rb` file."
|
8
|
+
elsif Twilio::Rails.config.host == "https://example.com"
|
9
|
+
puts "Twilio::Rails.config.host is set to a test value. Set it in the `config/initializers/twilio_rails.rb` file."
|
10
|
+
else
|
11
|
+
http_methods = if Twilio::Rails.config.controller_http_methods.length == 1
|
12
|
+
"HTTP #{ Twilio::Rails.config.controller_http_methods.first.to_s.upcase }"
|
13
|
+
else
|
14
|
+
"HTTP POST or HTTP GET"
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Log into the Twilio web console: https://console.twilio.com"
|
18
|
+
puts "Navigate to Phone Numbers -> Manage -> Active Numbers and find the phone number #{Twilio::Rails.config.default_outgoing_phone_number}."
|
19
|
+
puts ""
|
20
|
+
|
21
|
+
if Twilio::Rails.config.phone_trees.all.length == 0
|
22
|
+
puts "You cannot yet configure `Voice & Fax' because There are no phone trees registered in this application."
|
23
|
+
puts "Register them in the `config/initializers/twilio_rails.rb` file if you want to handle phone calls, and run this task again to help configure Twilio."
|
24
|
+
else
|
25
|
+
puts "Under 'Voice & Fax' set 'A CALL COMES IN' to 'Webhook' with #{ http_methods } and one of the following URLs:"
|
26
|
+
Twilio::Rails.config.phone_trees.all.each do |name, tree|
|
27
|
+
puts " #{tree.inbound_url}"
|
28
|
+
end
|
29
|
+
puts ""
|
30
|
+
puts "Under 'Voice & Fax' set 'CALL STATUS CHANGES' to following URL:"
|
31
|
+
puts " #{ ::Twilio::Rails.config.host }#{ ::Twilio::Rails::Engine.routes.url_helpers.phone_status_path(format: :xml) }"
|
32
|
+
end
|
33
|
+
|
34
|
+
puts ""
|
35
|
+
puts "Under 'Messaging' set 'A MESSAGE COMES IN' to 'Webhook' with #{ http_methods } and the following URL:"
|
36
|
+
puts " #{ ::Twilio::Rails.config.host }#{ ::Twilio::Rails::Engine.routes.url_helpers.sms_message_path(format: :xml) }"
|
37
|
+
|
38
|
+
if Twilio::Rails.config.sms_responders.all.length == 0
|
39
|
+
puts "There are no SMS responders registered so they will not be handled."
|
40
|
+
puts "Register them in the `config/initializers/twilio_rails.rb` file if you want to handle SMS messages."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Twilio
|
3
|
+
module Rails
|
4
|
+
# An abstraction over top of the `Twilio::REST` API client. Used to send SMS messages and start calls, as well as
|
5
|
+
# return an initialized client if needed.
|
6
|
+
module Client
|
7
|
+
extend self
|
8
|
+
|
9
|
+
# @return [Twilio::REST::Client] Twilio client initialized with `account_sid` and `auth_token` from the config.
|
10
|
+
def client
|
11
|
+
@twilio_client ||= Twilio::REST::Client.new(
|
12
|
+
Twilio::Rails.config.account_sid,
|
13
|
+
Twilio::Rails.config.auth_token,
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Do not call this directly, instead see {Twilio::Rails::SMS::SendOperation}. Send an SMS message to and from the
|
18
|
+
# given phone numbers using the Twilio REST API directly. This does not store or manage any interactions in the
|
19
|
+
# database.
|
20
|
+
#
|
21
|
+
# @param message [String] the message to send.
|
22
|
+
# @param to [String] the phone number to send the message to.
|
23
|
+
# @param from [String] the phone number to send the message from.
|
24
|
+
# @return [String] the SID returned from Twilio for the sent SMS message.
|
25
|
+
def send_message(message:, to:, from:)
|
26
|
+
Twilio::Rails.config.logger.tagged(self) { |l| l.info("[send_message] to=#{ to } from=#{ from } body='#{ message }'") }
|
27
|
+
client.messages.create(
|
28
|
+
from: from,
|
29
|
+
to: to,
|
30
|
+
body: message,
|
31
|
+
status_callback: "#{ Twilio::Rails.config.host }#{ ::Twilio::Rails::Engine.routes.url_helpers.sms_status_path(format: :xml) }",
|
32
|
+
).sid
|
33
|
+
end
|
34
|
+
|
35
|
+
# Do not call this directly, instead see {Twilio::Rails::SMS::SendOperation}. Sends multiple SMS messages to and
|
36
|
+
# from the given phone numbers using the Twilio REST API directly. This does not store or manage any interactions
|
37
|
+
# in the database. If a message is blank it will be ignored.
|
38
|
+
#
|
39
|
+
# @param messages [Array<String>] the messages to send.
|
40
|
+
# @param to [String] the phone number to send the messages to.
|
41
|
+
# @param from [String] the phone number to send the messages from.
|
42
|
+
# @return [Array<String>] the SIDs returned from Twilio for the sent SMS messages.
|
43
|
+
def send_messages(messages:, to:, from:)
|
44
|
+
Twilio::Rails.config.logger.tagged(self) { |l| l.info("[send_messages] to blank messages") } if messages.blank?
|
45
|
+
messages.map { |m| send_message(message: m, to: to, from: from) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Do not call this directly, instead see {Twilio::Rails::Phone::StartCallOperation}. Starts a phone call to and
|
49
|
+
# from the given phone numbers using the Twilio REST API directly. This does not store or manage any interactions
|
50
|
+
# in the database. The URL should come from the {Twilio::Rails::Phone::Tree} that is being used to start the call.
|
51
|
+
#
|
52
|
+
# @param url [String] the URL to use for the Twilio REST API call, probably from the {Twilio::Rails::Phone::Tree}.
|
53
|
+
# @param to [String] the phone number to make the call to.
|
54
|
+
# @param from [String] the phone number to make the call from.
|
55
|
+
# @param answering_machine_detection [true, false] whether or not to enable answering machine detection.
|
56
|
+
# @return [String] the SID returned from Twilio for the started call.
|
57
|
+
def start_call(url:, to:, from:, answering_machine_detection: true)
|
58
|
+
Twilio::Rails.config.logger.tagged(self) { |l| l.info("[start_call] to=#{ to } from=#{ from } url=#{ url } answering_machine_detection=#{ !!answering_machine_detection }") }
|
59
|
+
client.calls.create(
|
60
|
+
from: from,
|
61
|
+
to: to,
|
62
|
+
url: url,
|
63
|
+
machine_detection: ( answering_machine_detection ? "Enable" : "Disable" ),
|
64
|
+
async_amd: true,
|
65
|
+
async_amd_status_callback: "#{ Twilio::Rails.config.host }#{ ::Twilio::Rails::Engine.routes.url_helpers.phone_status_path(format: :xml, async_amd: "true") }",
|
66
|
+
async_amd_status_callback_method: "POST",
|
67
|
+
status_callback: "#{ Twilio::Rails.config.host }#{ ::Twilio::Rails::Engine.routes.url_helpers.phone_status_path(format: :xml) }",
|
68
|
+
status_callback_method: "POST",
|
69
|
+
status_callback_event: ["completed", "no-answer"],
|
70
|
+
# timeout: 30,
|
71
|
+
).sid
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Twilio
|
3
|
+
module Rails
|
4
|
+
# Provides scopes, validations, and convenience methods for a model that has an attribute `direction` with
|
5
|
+
# values "inbound" or "outbound".
|
6
|
+
module HasDirection
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
validates :direction, inclusion: { in: ["outbound", "inbound"] }
|
11
|
+
|
12
|
+
scope :outbound, -> { where(direction: "outbound") }
|
13
|
+
scope :inbound, -> { where(direction: "inbound") }
|
14
|
+
end
|
15
|
+
|
16
|
+
def inbound?
|
17
|
+
direction == "inbound"
|
18
|
+
end
|
19
|
+
|
20
|
+
def outbound?
|
21
|
+
direction == "outbound"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Twilio
|
3
|
+
module Rails
|
4
|
+
# Provides validations and reformatting on validation for a model that has an attribute `phone_number` that is
|
5
|
+
# that is unique and that matches {Twilio::Rails::Formatter.coerce_to_valid_phone_number}.
|
6
|
+
module HasPhoneNumber
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
validates :phone_number, uniqueness: { allow_blank: true, message: "already exists" }
|
11
|
+
|
12
|
+
before_validation :reformat_phone_number
|
13
|
+
end
|
14
|
+
|
15
|
+
def reformat_phone_number
|
16
|
+
current = Twilio::Rails::Formatter.coerce_to_valid_phone_number(phone_number)
|
17
|
+
self.phone_number = current if current
|
18
|
+
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_north_american_phone_number?
|
23
|
+
Twilio::Rails::Formatter.valid_north_american_phone_number?(phone_number)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Twilio
|
3
|
+
module Rails
|
4
|
+
# Provides convenience scopes for a model that has a `created_at` attribute.
|
5
|
+
module HasTimeScopes
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
scope :in_last, ->(time) { where(created_at: (Time.now - time)..(Time.now)) }
|
10
|
+
scope :in_previous, ->(time) { where(created_at: (Time.now - time - time)..(Time.now - time)) }
|
11
|
+
|
12
|
+
scope :in_last_24_hours, -> { in_last(1.day) }
|
13
|
+
scope :in_last_2_days, -> { in_last(2.days) }
|
14
|
+
scope :in_last_4_hours, -> { in_last(4.hours) }
|
15
|
+
scope :in_previous_24_hours, -> { in_previous(1.day) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|