Skip to content

Commit

Permalink
Cache Touchpoint Form
Browse files Browse the repository at this point in the history
  • Loading branch information
aktfrikshun authored and ryanwoldatwork committed Nov 26, 2019
1 parent 7388720 commit dd40cc0
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 41 deletions.
1 change: 0 additions & 1 deletion .cfignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
/yarn-error.log

/public/assets
.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key
Expand Down
3 changes: 3 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ LOGIN_GOV_REDIRECT_URI='http://localhost:3002/users/auth/login_dot_gov/callback'
# For New Relic
NEW_RELIC_KEY=YOUR-NEW-RELIC-KEY-HERE

# Redis cache store
REDIS_CACHE_STORE=redis://localhost:6379/1

# For image uploads
S3_AWS_ACCESS_KEY_ID=
S3_AWS_SECRET_ACCESS_KEY=
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
/yarn-error.log

/public/assets
.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key
Expand Down
9 changes: 2 additions & 7 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,12 @@ gem 'rack-cors', require: 'rack/cors'
gem 'sass-rails'
gem 'sidekiq'
gem 'uglifier'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Redis to cache Touchpoints in all envs
gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'dotenv-rails'
gem 'pry'
gem 'rspec_junit_formatter'
Expand Down
3 changes: 1 addition & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ GEM
bindata (2.4.4)
bindex (0.8.1)
builder (3.2.3)
byebug (11.0.1)
capybara (3.29.0)
addressable
mini_mime (>= 0.1.3)
Expand Down Expand Up @@ -330,7 +329,6 @@ PLATFORMS

DEPENDENCIES
aws-sdk-rails
byebug
capybara
caracal
carrierwave
Expand All @@ -352,6 +350,7 @@ DEPENDENCIES
puma
rack-cors
rails (~> 5.2.1)
redis (~> 4.0)
rspec-rails
rspec_junit_formatter
sass-rails
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/submissions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def create
end

@submission = Submission.new(submission_params)
@submission.touchpoint_id = @touchpoint.id
@submission.touchpoint = @touchpoint
@submission.user_agent = request.user_agent
@submission.referer = submission_params[:referer]
@submission.page = submission_params[:page]
Expand Down Expand Up @@ -90,9 +90,9 @@ def create_in_local_database(submission)

def set_touchpoint
if params[:touchpoint] # coming from /touchpoints/:id/submit
@touchpoint = Touchpoint.find(params[:id])
@touchpoint = TouchpointCache.fetch(params[:id])
else
@touchpoint = Touchpoint.find(params[:touchpoint_id])
@touchpoint = TouchpointCache.fetch(params[:touchpoint_id])
end
raise InvalidArgument("Touchpoint does not exist") unless @touchpoint
end
Expand Down
17 changes: 9 additions & 8 deletions app/models/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ class Form < ApplicationRecord
validates :character_limit, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 100000 }
validates_length_of :disclaimer_text, in: 0..500, allow_blank: true

after_create :create_first_form_section

def create_first_form_section
self.form_sections.create(title: (I18n.t 'form.page_1'), position: 1)
after_initialize do |user|
self.modal_button_text = I18n.t('form.help_improve')
self.success_text = I18n.t('form.submit_thankyou')
end

def success_text
super.present? ? super : (I18n.t 'form.submit_thankyou')
after_create :create_first_form_section

after_save do |form|
TouchpointCache.invalidate(form.touchpoint.id) if form.touchpoint.present?
end

def modal_button_text
super.present? ? super : (I18n.t 'form.help_improve')
def create_first_form_section
self.form_sections.create(title: (I18n.t 'form.page_1'), position: 1)
end
end
7 changes: 4 additions & 3 deletions app/models/form_section.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ class FormSection < ApplicationRecord
belongs_to :form
has_many :questions

after_save do | form_section |
TouchpointCache.invalidate(form_section.form.touchpoint.id) if form_section.form.touchpoint.present?
end

default_scope { order(position: :asc) }

def title
super ? super : "Unnamed Form Section Title"
end
end
4 changes: 4 additions & 0 deletions app/models/question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ class Question < ApplicationRecord
validates :answer_field, presence: true
validates :character_limit, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 100000, allow_nil: true }

after_save do | question |
TouchpointCache.invalidate(question.form.touchpoint.id) if question.form.touchpoint.present?
end

default_scope { order(position: :asc) }
end
4 changes: 4 additions & 0 deletions app/models/question_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ class QuestionOption < ApplicationRecord

validates :position, presence: true

after_save do | question_option |
TouchpointCache.invalidate(question_option.question.form.touchpoint.id) if question_option.question.form.touchpoint.present?
end

default_scope { order(position: :asc) }
end
4 changes: 4 additions & 0 deletions app/models/touchpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ class Touchpoint < ApplicationRecord

validate :omb_number_with_expiration_date

after_save do |touchpoint|
TouchpointCache.invalidate(touchpoint.id)
end

def omb_number_with_expiration_date
if omb_approval_number.present? && !expiration_date.present?
errors.add(:expiration_date, "required with an OMB Number")
Expand Down
18 changes: 18 additions & 0 deletions app/models/touchpoint_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class TouchpointCache

TOUCHPOINT_NAMESPACE = "namespace:touchpoint-"

# Cache Store fetch will return the cached item
# or run the block if the cached item does not exist
def self.fetch(id)
Rails.cache.fetch(TOUCHPOINT_NAMESPACE + id.to_s, expires_in: 1.day) do
#Pull in all objects required to build a touchpoint
Touchpoint.includes({form: [:questions, form_sections: [questions: [:question_options]]]}, service: [:organization]).find(id)
end
end

def self.invalidate(id)
Rails.cache.delete(TOUCHPOINT_NAMESPACE + id.to_s)
end

end
18 changes: 2 additions & 16 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.

# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false

# Do not eager load code on boot.
config.eager_load = false

Expand All @@ -14,17 +9,8 @@

# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true

config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false

config.cache_store = :null_store
Rails.application.configure do
config.cache_store = :redis_cache_store, { url: ENV["REDIS_CACHE_STORE"] }
end

# Store uploaded files on the local file system (see config/storage.yml for options)
Expand Down
3 changes: 3 additions & 0 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@

# Use a different cache store in production.
# config.cache_store = :mem_cache_store
Rails.application.configure do
config.cache_store = :redis_cache_store, { url: ENV["REDIS_CACHE_STORE"] }
end

# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
Expand Down
3 changes: 3 additions & 0 deletions config/environments/staging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@

# Use a different cache store in production.
# config.cache_store = :mem_cache_store
Rails.application.configure do
config.cache_store = :redis_cache_store, { url: ENV["REDIS_CACHE_STORE"] }
end

# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
Expand Down
1 change: 1 addition & 0 deletions spec/features/touchpoints_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
context "custom success text" do
before do
touchpoint.form.update_attribute(:success_text, "Much success, yessss.")
touchpoint.reload
visit touchpoint_path(touchpoint)
expect(page.current_path).to eq("/touchpoints/#{touchpoint.id}/submit")
expect(page).to have_content("OMB Approval ##{touchpoint.omb_approval_number}")
Expand Down
27 changes: 27 additions & 0 deletions spec/models/touchpoint_cache_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'rails_helper'

RSpec.describe TouchpointCache, type: :model do

let!(:touchpoint) { FactoryBot.create(:touchpoint, :with_form) }

describe "validate cache fetch" do
context "Store and Fetch Touchpoint" do
it "caches a touchpoint" do
@tpc = TouchpointCache.fetch(touchpoint.id)
expect(touchpoint.id).to eq(@tpc.id)
end
end

context "Invalidate Cache" do
before do
@tpc = TouchpointCache.fetch(touchpoint.id)
expect(touchpoint.id).to eq(@tpc.id)
TouchpointCache.invalidate(touchpoint.id)
end

it "removes a touchpoint from cache" do
expect(Rails.cache.read("namespace:touchpoint-" + touchpoint.id.to_s)).to eq(nil)
end
end
end
end

0 comments on commit dd40cc0

Please sign in to comment.