├── spec ├── fixtures │ ├── spec │ │ └── models │ │ │ └── hoge_spec.rb │ └── app │ │ └── models │ │ └── hoge.rb ├── rails-open-rspec-view-spec.coffee └── rails-open-rspec-spec.coffee ├── .gitignore ├── CHANGELOG.md ├── keymaps └── rails-open-rspec.cson ├── rails-open-rspec.gif ├── styles └── rails-open-rspec.less ├── menus └── rails-open-rspec.cson ├── package.json ├── lib ├── rails-open-rspec-view.coffee ├── spec-writer.coffee └── rails-open-rspec.coffee ├── LICENSE.md └── README.md /spec/fixtures/spec/models/hoge_spec.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.0 - First Release 2 | * Every feature added 3 | * Every bug fixed 4 | -------------------------------------------------------------------------------- /keymaps/rails-open-rspec.cson: -------------------------------------------------------------------------------- 1 | 'atom-text-editor': 2 | 'cmd-alt-o': 'rails-open-rspec:open-rspec-file' 3 | -------------------------------------------------------------------------------- /rails-open-rspec.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harada4atsushi/rails-open-rspec/HEAD/rails-open-rspec.gif -------------------------------------------------------------------------------- /spec/fixtures/app/models/hoge.rb: -------------------------------------------------------------------------------- 1 | class Hoge 2 | def say_hoge 3 | end 4 | 5 | def active? 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/rails-open-rspec-view-spec.coffee: -------------------------------------------------------------------------------- 1 | #RailsOpenRspecView = require '../lib/rails-open-rspec-view' 2 | 3 | describe "RailsOpenRspecView", -> 4 | # it "has one valid test", -> 5 | # expect("life").toBe "easy" 6 | -------------------------------------------------------------------------------- /styles/rails-open-rspec.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | .rails-open-rspec { 8 | } 9 | -------------------------------------------------------------------------------- /menus/rails-open-rspec.cson: -------------------------------------------------------------------------------- 1 | # See https://atom.io/docs/latest/hacking-atom-package-word-count#menus for more details 2 | 'context-menu': 3 | 'atom-text-editor': [ 4 | { 5 | 'label': 'Toggle rails-open-rspec' 6 | 'command': 'rails-open-rspec:toggle' 7 | } 8 | ] 9 | 'menu': [ 10 | { 11 | 'label': 'Packages' 12 | 'submenu': [ 13 | 'label': 'rails-open-rspec' 14 | 'submenu': [ 15 | { 16 | 'label': 'Toggle' 17 | 'command': 'rails-open-rspec:toggle' 18 | } 19 | ] 20 | ] 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rails-open-rspec", 3 | "main": "./lib/rails-open-rspec", 4 | "version": "1.2.0", 5 | "description": "open rspec file by current file.", 6 | "activationCommands": { 7 | "atom-workspace": [ 8 | "rails-open-rspec:open-rspec-file" 9 | ] 10 | }, 11 | "repository": "https://github.com/harada4atsushi/rails-open-rspec", 12 | "license": "MIT", 13 | "engines": { 14 | "atom": ">=0.174.0 <2.0.0" 15 | }, 16 | "dependencies": {}, 17 | "configSchema": { 18 | "splitPane": { 19 | "description": "Open specs side by side with code.", 20 | "type": "boolean", 21 | "default": true, 22 | "order": 1 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/rails-open-rspec-view.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class RailsOpenRspecView 3 | constructor: (serializedState) -> 4 | # Create root element 5 | @element = document.createElement('div') 6 | @element.classList.add('rails-open-rspec') 7 | 8 | # Create message element 9 | message = document.createElement('div') 10 | message.textContent = "The RailsOpenRspec package is Alive! It's ALIVE!" 11 | message.classList.add('message') 12 | @element.appendChild(message) 13 | 14 | # Returns an object that can be retrieved when package is activated 15 | serialize: -> 16 | 17 | # Tear down any state and detach 18 | destroy: -> 19 | @element.remove() 20 | 21 | getElement: -> 22 | @element 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Atsushi Harada 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rails Open Rspec Package 2 | 3 | ![Rails Open Rspec](https://raw.github.com/harada4atsushi/rails-open-rspec/master/rails-open-rspec.gif) 4 | 5 | ## Installation 6 | ```sh 7 | apm install rails-open-rspec 8 | ``` 9 | or find it in the Packages tab under settings 10 | 11 | ## Usage 12 | `option-cmd-o` or **Rails Open Rspec: Open Rspec File** in the Command Palette. 13 | 14 | Open rspec file from current file to window split right. 15 | If current file is spec file, open production file to window split left. 16 | 17 | ## Job offer (English) 18 | TODO 19 | 20 | ## Job offer (Japanese) 21 | 22 | 本パッケージの作者、エンジニア兼代表取締役が原田 敦が経営する[mofmof inc.](http://www.mof-mof.co.jp/)ではエンジニア(Ruby on Rails, 機械学習)を募集しております。少しでも興味がありましたら[採用情報ページ](http://www.recruit.mof-mof.co.jp/)のメールフォームからお問い合わせください。ぜひお茶でもしましょう。 23 | 24 | #### 必須 25 | 26 | - Python機械学習の実務経験、もしくはRuby on Railsでの実務経験どちらか必須 27 | - 経験のない技術をキャッチアップすることが楽しみな方 28 | - コードレビューなど技術を磨くためのプロセスがあるため、指摘に対して謙虚に受け止められること、他人に対しておもいやりを持って話が出来ることが必要 29 | - 年齢・性別は不問だが、社会人経験があること 30 | 31 | #### 歓迎 32 | 33 | - Pythonで機械学習の実務開発経験があること 34 | - Ruby on Railsでの実務開発経験があること 35 | - 学生時代にコンピューターサイエンス専攻であること 36 | -------------------------------------------------------------------------------- /spec/rails-open-rspec-spec.coffee: -------------------------------------------------------------------------------- 1 | Path = require 'path' 2 | {Workspace} = require 'atom' 3 | RailsOpenRspec = require '../lib/rails-open-rspec' 4 | 5 | describe "RailsOpenRspec", -> 6 | [workspaceElement, activationPromise] = [] 7 | specFileOpened = null 8 | 9 | currentPath = -> 10 | atom.workspace.getActiveTextEditor().getPath() 11 | 12 | openRspecFile = (filePath) -> 13 | promise = atom.workspace.open(filePath) 14 | promise.then (editor) -> 15 | atom.commands.dispatch atom.views.getView(editor), 'rails-open-rspec:open-rspec-file' 16 | specFileOpened = true 17 | 18 | beforeEach -> 19 | workspaceElement = atom.views.getView(atom.workspace) 20 | activationPromise = atom.packages.activatePackage('rails-open-rspec') 21 | 22 | describe "when the rails-open-rspec:open-rspec-file event is triggered", -> 23 | it "open spec file", -> 24 | openRspecFile('app/models/hoge.rb') 25 | 26 | waitsFor -> 27 | specFileOpened 28 | 29 | runs -> 30 | # wait for open rspec file 31 | setTimeout -> 32 | console.log("") 33 | , 1000 34 | expect(currentPath()).toBe Path.join(__dirname, 'fixtures/spec/models/hoge_spec.rb') 35 | -------------------------------------------------------------------------------- /lib/spec-writer.coffee: -------------------------------------------------------------------------------- 1 | Path = require 'path' 2 | Fs = require 'fs' 3 | 4 | module.exports = 5 | class SpecWriter 6 | constructor: (@editor, @sourceEditor) -> 7 | @specType = @judgeSpecType() 8 | @helperName = @helperNameBeRequire() 9 | @methodNames = @detectMethodNames() 10 | @className = @detectClassName() 11 | 12 | write: -> 13 | @editor.insertText("require '#{@helperName}'\n") 14 | @editor.insertNewline() 15 | @editor.insertText("RSpec.describe #{@className}") 16 | 17 | if @specType? 18 | @editor.insertText(", :type => :#{@specType} do\n") 19 | else 20 | @editor.insertText(" do\n") 21 | 22 | for methodName in @methodNames 23 | @editor.insertText(" describe '##{methodName}' do\n", autoIndent: false) 24 | @editor.insertText(" end\n", autoIndent: false) 25 | @editor.insertNewline() 26 | @editor.insertText("end") 27 | 28 | judgeSpecType: -> 29 | dirName = Path.dirname(@editor.getPath()) 30 | if /\/models$/.test(dirName) 31 | type = 'model' 32 | else if /\/controllers$/.test(dirName) 33 | type = 'controller' 34 | else if /\/services$/.test(dirName) 35 | type = 'service' 36 | else 37 | type = null 38 | type 39 | 40 | detectMethodNames: -> 41 | lines = @sourceEditor.getBuffer().getLines() 42 | defLines = lines.map (line) -> 43 | arr = line.match(/^\s*def ([^\(]*)/) 44 | arr[1] if arr 45 | 46 | defLines.filter (line) -> line? 47 | 48 | detectClassName: -> 49 | #basename = Path.basename(@editor.getPath()) 50 | #className = basename.replace(/\_spec.rb$/, '').camelize() 51 | lines = @sourceEditor.getBuffer().getLines() 52 | arr = lines.filter (line) -> 53 | /^\s*class\s.*/.test(line) 54 | 55 | return null if arr.count == 0 56 | 57 | classNameLine = arr[0] 58 | expResult = classNameLine.match(/^\s*class\s(\S*)/) 59 | expResult[1] 60 | 61 | helperNameBeRequire: -> 62 | rootPath = atom.project.getPaths()[0] 63 | if Fs.existsSync("#{rootPath}/spec/rails_helper.rb") 64 | 'rails_helper' 65 | else 66 | 'spec_helper' 67 | -------------------------------------------------------------------------------- /lib/rails-open-rspec.coffee: -------------------------------------------------------------------------------- 1 | RailsOpenRspecView = require './rails-open-rspec-view' 2 | SpecWriter = require './spec-writer' 3 | 4 | {CompositeDisposable} = require 'atom' 5 | {TextEditor} = require 'atom' 6 | 7 | fs = require 'fs' 8 | Path = require 'path' 9 | 10 | String::camelize =-> 11 | @replace /(^|\-|\_)(\w)/g, (a,b,c)-> 12 | c.toUpperCase() 13 | 14 | module.exports = 15 | activate: (state) -> 16 | atom.commands.add 'atom-workspace', "rails-open-rspec:open-rspec-file", => @openSpec() 17 | 18 | openSpec: -> 19 | sourceEditor = atom.workspace.getActiveTextEditor() 20 | return if !sourceEditor 21 | 22 | currentFilepath = sourceEditor.getPath() 23 | openFilePath = @findFilepath(currentFilepath) 24 | 25 | return if openFilePath == null 26 | @openWithWrite(openFilePath, sourceEditor) 27 | 28 | findFilepath: (currentFilepath) -> 29 | rootPath = atom.project.getPaths()[0] 30 | relativePath = currentFilepath.substring(rootPath.length) 31 | 32 | if @isSpecFile(relativePath) 33 | openFilePath = relativePath.replace /\_spec\.rb$/, '.rb' 34 | openFilePath = openFilePath.replace /^\/spec\/lib\//, "/lib/" 35 | openFilePath = openFilePath.replace /^\/spec\//, "/app/" 36 | else 37 | openFilePath = relativePath.replace /\.rb$/, '_spec.rb' 38 | openFilePath = openFilePath.replace /^\/lib\//, "/spec/lib/" 39 | openFilePath = openFilePath.replace /^\/app\//, "/spec/" 40 | 41 | if relativePath == openFilePath 42 | null 43 | else 44 | Path.join rootPath, openFilePath 45 | 46 | isSpecFile: (path) -> 47 | /_spec\.rb/.test(path) 48 | 49 | isSinglePane: -> 50 | atom.workspace.getPanes().length == 1 51 | 52 | openWithWrite: (openFilePath, sourceEditor) -> 53 | openOptions = {} 54 | if atom.config.get('rails-open-rspec.splitPane') 55 | if @isSinglePane() 56 | openOptions = { split: 'right' } 57 | else 58 | atom.workspace.activateNextPane() 59 | 60 | promise = atom.workspace.open(openFilePath, openOptions) 61 | 62 | promise.then (specEditor) -> 63 | if specEditor.isEmpty() 64 | specWriter = new SpecWriter(specEditor, sourceEditor) 65 | atom.notifications.addInfo("Generate new spec") 66 | specWriter.write() 67 | --------------------------------------------------------------------------------