Last active
April 14, 2020 12:24
-
-
Save AndrewRadev/5f9990add6ad4ab8986aa6185735b7f9 to your computer and use it in GitHub Desktop.
An `:Efactory` command for jumping to factory_bot definitions in rails projects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" Extracted from: | |
" https://github.com/AndrewRadev/Vimfiles/blob/0490041cf2d0e4f7a9b2e1361bb47971dd59d836/miniplugins/plugin/rails_extra.vim | |
" | |
" Installation: | |
" | |
" Copy file to ~/.vim/plugin/efactory.vim, or just paste the whole thing in | |
" your `.vimrc`. No guarantees it'll work well for you, seems to work for me. | |
" Will extract to a plugin at some point and it'll hopefully be more reliable. | |
" | |
" Usage: | |
" | |
" :Efactory <factory-name> | |
" | |
" The factory list tab-completes names from factory files in expected | |
" locations, see `s:FindFactoryFiles` below for the glob patterns it goes | |
" through. | |
" Define the :Efactory command only in files within rails apps (using rails.vim): | |
" | |
augroup Efactory | |
autocmd! | |
autocmd User Rails command! -buffer -nargs=* -complete=custom,s:CompleteFactories | |
\ Efactory call s:Efactory(<q-args>) | |
augroup END | |
" Or, define the :Efactory command globally: | |
" | |
" command! -nargs=* -complete=custom,s:CompleteFactories | |
" \ Efactory call s:Efactory(<q-args>) | |
function! s:Efactory(factory_name) | |
let factory_name = a:factory_name | |
if factory_name == '' | |
let factory_name = s:CurrentModelName() | |
endif | |
let [filename, lineno] = s:FindFactory(factory_name) | |
if filename != '' | |
exe 'edit '.filename | |
exe lineno | |
else | |
echohl WarningMsg | echomsg "Factory not found: ".factory_name | echohl NONE | |
endif | |
endfunction | |
function! s:CompleteFactories(_A, _L, _P) | |
let factory_names = [] | |
for filename in s:FindFactoryFiles() | |
for line in readfile(filename) | |
let pattern = '^\s*factory :\zs\k\+\ze\s*\%(,\|do\)' | |
if line =~ pattern | |
call add(factory_names, matchstr(line, pattern)) | |
endif | |
endfor | |
endfor | |
call sort(factory_names) | |
call uniq(factory_names) | |
return join(factory_names, "\n") | |
endfunction | |
function! s:CurrentModelName() | |
let current_file = expand('%:p') | |
if current_file =~ 'app/models/.*\.rb$' | |
let filename = expand('%:t:r') | |
return filename | |
else | |
return '' | |
endif | |
endfunction | |
function! s:FindFactory(name) | |
let pattern = '^\s*factory :'.a:name.'\>' | |
for filename in s:FindFactoryFiles() | |
let lineno = 1 | |
for line in readfile(filename) | |
if line =~ pattern | |
return [filename, lineno] | |
endif | |
let lineno += 1 | |
endfor | |
endfor | |
return ['', -1] | |
endfunction | |
function! s:FindFactoryFiles() | |
let factory_files = [] | |
if exists('b:rails_root') | |
let root = b:rails_root | |
else | |
" assume we're in the root of the application | |
let root = '.' | |
endif | |
for test_dir in ['test', 'spec'] | |
call extend(factory_files, split(glob(root.'/'.test_dir.'/**/factories.rb'), "\n")) | |
call extend(factory_files, split(glob(root.'/'.test_dir.'/**/factories/*.rb'), "\n")) | |
call extend(factory_files, split(glob(root.'/'.test_dir.'/**/factories/**/*.rb'), "\n")) | |
endfor | |
return factory_files | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment