Skip to content

Commit

Permalink
Validate detected instance_variable is an ActiveRecord::Relation
Browse files Browse the repository at this point in the history
  • Loading branch information
makicamel committed Nov 12, 2023
1 parent 53ab87b commit 86497bd
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/bulletmark_repairer/markers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ def set_up
end
view_file, view_yield_index = @stacktraces[view_file_index].scan(%r{\A(/[./\w]+):(\d+):in `[\w]+'\z}).flatten
view_yield_index = view_yield_index.to_i
# TODO: Compile views
File.open(view_file) do |f|
lines = f.readlines
loop do
break if @instance_variable_name || view_yield_index.zero?

view_yield_index -= 1
line = lines[view_yield_index]
@instance_variable_name = line&.scan(/\b?(@[\w]+)\b?/)&.flatten&.last
token = line&.scan(/\b?(@[\w]+)\b?/)&.flatten&.last
@instance_variable_name = token if BulletmarkRepairer::Thread.instance_variable_name?(token)
end
end
@index = @instance_variable_name ? "#{view_file}:#{view_yield_index}" : nil
Expand Down
14 changes: 14 additions & 0 deletions lib/bulletmark_repairer/monkey_patches/action_view/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module BulletmarkRepairer
module ActionView
module Base
def initialize(*args)
super(*args)
@_assigns.each do |ivname, value|
BulletmarkRepairer::Thread.memorize_instance_variable_name(name: ivname, value: value)
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/bulletmark_repairer/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ class Railtie < ::Rails::Railtie
require 'bulletmark_repairer/monkey_patches/active_record/query_method'
::ActiveRecord::Relation.prepend(BulletmarkRepairer::ActiveRecord::QueryMethod)
end
ActiveSupport.on_load(:action_view) do
require 'bulletmark_repairer/monkey_patches/action_view/base'
::ActionView::Base.prepend(BulletmarkRepairer::ActionView::Base)
end
end
end
10 changes: 10 additions & 0 deletions lib/bulletmark_repairer/thread.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ def memorize_associations(name:, method_type:, args:)
current(:loaded_associations)[name][method_type].add(args)
end

def memorize_instance_variable_name(name:, value:)
return unless value.is_a?(::ActiveRecord::Relation)

current(:loaded_instance_variables).add("@#{name}")
end

def instance_variable_name?(name)
current(:loaded_instance_variables).include?(name)
end

def clear
::Thread.current[:bulletmark_repairer] = nil
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class InstanceVariablesController < ActionController::Base
def index
@favorite = true
@plays = Play.all
end
end
8 changes: 8 additions & 0 deletions spec/fake_app/app/views/instance_variables/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<% plays = @plays %>
<% if @favorite %>
<% plays.each do |play| %>
<% play.actors.each do |actor| %>
<%= actor.name %>
<% end %>
<% end %>
<% end %>
1 change: 1 addition & 0 deletions spec/fake_app/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
resources :multiple_nested_though_only_grand_child_is_required_includes, only: [:index]
resources :another_name_associations, only: [:index]
resources :nested_and_another_name_includes, only: [:index]
resources :instance_variables, only: [:index]
resources :avoid_includes, only: [:index]
end
31 changes: 31 additions & 0 deletions spec/requests/instance_variables_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe InstanceVariablesController do
let(:original_src) do
<<-SRC
def index
@favorite = true
@plays = Play.all
end
SRC
end
let(:patched_src) do
<<-SRC
def index
@favorite = true
@plays = Play.all.includes([:actors])
end
SRC
end

before do
create(:play, :blast)
create(:play, :crescent_wolf)
end

subject { get instance_variables_path }

it_behaves_like 'correctly patched'
end

0 comments on commit 86497bd

Please sign in to comment.