diff options
author | Rémy Coutable <remy@rymai.me> | 2017-11-13 15:27:30 +0000 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2017-11-13 15:27:30 +0000 |
commit | 1c116bc95f5e55360e3c3e22c96fc6a617d62c74 (patch) | |
tree | 366d7dfbd59ce1e64ec46eb98ea36c83317d02df | |
parent | 4a1e8188f96744103e51263c9bdc071c8e088690 (diff) | |
parent | 258bf3e187538bd326491e5d1b25a0511fbd96a1 (diff) | |
download | gitlab-ce-1c116bc95f5e55360e3c3e22c96fc6a617d62c74.tar.gz |
Merge branch '39842-fetch-ivar' into 'master'
Add Gitlab::Utils::StrongMemoize
Allows patterns like this:
def trigger_from_token
return @Trigger if defined?(@Trigger)
@Trigger = Ci::Trigger.find_by_token(params[:token].to_s)
end
Closes #39842
See merge request gitlab-org/gitlab-ce!15222
-rw-r--r-- | app/services/ci/pipeline_trigger_service.rb | 8 | ||||
-rw-r--r-- | lib/api/api_guard.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/utils/strong_memoize.rb | 31 | ||||
-rw-r--r-- | spec/lib/gitlab/utils/strong_memoize_spec.rb | 52 |
4 files changed, 93 insertions, 6 deletions
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb index 120af8c1e61..a9813d774bb 100644 --- a/app/services/ci/pipeline_trigger_service.rb +++ b/app/services/ci/pipeline_trigger_service.rb @@ -1,5 +1,7 @@ module Ci class PipelineTriggerService < BaseService + include Gitlab::Utils::StrongMemoize + def execute if trigger_from_token create_pipeline_from_trigger(trigger_from_token) @@ -26,9 +28,9 @@ module Ci end def trigger_from_token - return @trigger if defined?(@trigger) - - @trigger = Ci::Trigger.find_by_token(params[:token].to_s) + strong_memoize(:trigger) do + Ci::Trigger.find_by_token(params[:token].to_s) + end end def create_pipeline_variables!(pipeline) diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb index b9c7d443f6c..c1c0d344917 100644 --- a/lib/api/api_guard.rb +++ b/lib/api/api_guard.rb @@ -42,6 +42,8 @@ module API # Helper Methods for Grape Endpoint module HelperMethods + include Gitlab::Utils::StrongMemoize + def find_current_user! user = find_user_from_access_token || find_user_from_warden return unless user @@ -52,9 +54,9 @@ module API end def access_token - return @access_token if defined?(@access_token) - - @access_token = find_oauth_access_token || find_personal_access_token + strong_memoize(:access_token) do + find_oauth_access_token || find_personal_access_token + end end def validate_access_token!(scopes: []) diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb new file mode 100644 index 00000000000..a2ac9285b56 --- /dev/null +++ b/lib/gitlab/utils/strong_memoize.rb @@ -0,0 +1,31 @@ +module Gitlab + module Utils + module StrongMemoize + # Instead of writing patterns like this: + # + # def trigger_from_token + # return @trigger if defined?(@trigger) + # + # @trigger = Ci::Trigger.find_by_token(params[:token].to_s) + # end + # + # We could write it like: + # + # def trigger_from_token + # strong_memoize(:trigger) do + # Ci::Trigger.find_by_token(params[:token].to_s) + # end + # end + # + def strong_memoize(name) + ivar_name = "@#{name}" + + if instance_variable_defined?(ivar_name) + instance_variable_get(ivar_name) + else + instance_variable_set(ivar_name, yield) + end + end + end + end +end diff --git a/spec/lib/gitlab/utils/strong_memoize_spec.rb b/spec/lib/gitlab/utils/strong_memoize_spec.rb new file mode 100644 index 00000000000..4a104ab6d97 --- /dev/null +++ b/spec/lib/gitlab/utils/strong_memoize_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe Gitlab::Utils::StrongMemoize do + let(:klass) do + struct = Struct.new(:value) do + def method_name + strong_memoize(:method_name) do + trace << value + value + end + end + + def trace + @trace ||= [] + end + end + + struct.include(described_class) + struct + end + + subject(:object) { klass.new(value) } + + shared_examples 'caching the value' do + it 'only calls the block once' do + value0 = object.method_name + value1 = object.method_name + + expect(value0).to eq(value) + expect(value1).to eq(value) + expect(object.trace).to contain_exactly(value) + end + + it 'returns and defines the instance variable for the exact value' do + returned_value = object.method_name + memoized_value = object.instance_variable_get(:@method_name) + + expect(returned_value).to eql(value) + expect(memoized_value).to eql(value) + end + end + + describe '#strong_memoize' do + [nil, false, true, 'value', 0, [0]].each do |value| + context "with value #{value}" do + let(:value) { value } + + it_behaves_like 'caching the value' + end + end + end +end |