rails_zen 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +102 -0
- data/Rakefile +8 -0
- data/bin/rails_zen +4 -0
- data/features/model/act.feature +49 -0
- data/features/model/g.feature +64 -0
- data/features/step_definitions/mock_file_steps.rb +18 -0
- data/features/support/env.rb +9 -0
- data/lib/cli.rb +10 -0
- data/lib/cli/model.rb +33 -0
- data/lib/rails_zen.rb +5 -0
- data/lib/rails_zen/chosen_attr.rb +89 -0
- data/lib/rails_zen/given_model_gen.rb +76 -0
- data/lib/rails_zen/model_action.rb +106 -0
- data/lib/rails_zen/version.rb +3 -0
- data/lib/rails_zen/write_to_files.rb +31 -0
- data/lib/rails_zen/write_to_files/model_level_validation.rb +12 -0
- data/lib/rails_zen/write_to_files/model_level_validation_spec.rb +14 -0
- data/lib/rails_zen/write_to_files/write_to_migration.rb +37 -0
- data/lib/rails_zen/write_to_files/write_to_model.rb +57 -0
- data/lib/rails_zen/write_to_files/write_to_spec.rb +45 -0
- data/lib/railtie.rb +8 -0
- data/rails_zen.gemspec +29 -0
- data/spec/chosen_attr_spec.rb +92 -0
- data/spec/given_model_gen_spec.rb +81 -0
- data/spec/model_action_spec.rb +81 -0
- data/spec/shared/build_file_attr.rb +12 -0
- data/spec/spec_helper.rb +93 -0
- data/spec/support/aruba.rb +11 -0
- data/spec/write_to_files/write_to_migration_spec.rb +50 -0
- data/spec/write_to_files/write_to_model_spec.rb +57 -0
- data/spec/write_to_files/write_to_spec_spec.rb +63 -0
- data/spec/write_to_files_spec.rb +9 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ffdf4939e8dda4d2ca2dca549392f46b0a417a3a
|
4
|
+
data.tar.gz: 33d799f39f4be8726d9ba7b4f7da2a8b6a35acc7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4d845aade057e447bb8860e6179286e9628ec4b8e3194ff59690ca08774a6d504640d109297a5d5a67f012e4719750ef1b9576a2674477cfeaf4b1e2994c7d88
|
7
|
+
data.tar.gz: 2d67d68126efc3db3158436f616e16917e1ed2b57f47fe17473eedfe946c0e62adcc7383555d6f0f4741a3e4f62c7f946498945e84ac5564e62ece24e0afb9f5
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Vysakh Sreenivasan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# RailsZen
|
2
|
+
|
3
|
+
**AIM**: To save time by giving a boilerplate, and a thought flow.
|
4
|
+
|
5
|
+
A step by step generator. This will get *uniqueness*, *validations* from you, and write
|
6
|
+
the appropriate files (model, migration, model_spec).
|
7
|
+
|
8
|
+
The specs generated here assumes you are using
|
9
|
+
|
10
|
+
- Rspec (>3.0)
|
11
|
+
- Shoulda matchers
|
12
|
+
- FactoryGirl
|
13
|
+
|
14
|
+
*NOTE*: You need to use this app at the root of your rails directory
|
15
|
+
|
16
|
+
*Disclamier*: Things like mocks, stubs and proper testing might not be possible with this project.
|
17
|
+
The aim is to automate as many things as possible, this is not a panacea :) .
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'rails_zen'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install rails_zen
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
### COMMANDS
|
38
|
+
|
39
|
+
#### model g (generate)
|
40
|
+
|
41
|
+
rails_zen model g user name:string score:integer
|
42
|
+
|
43
|
+
- Once you enter this command, you will have few questions asked such as what to validate, which attribute is unique.
|
44
|
+
- Based on your input, the model, model_spec and migration files will be written
|
45
|
+
|
46
|
+
#### model act (action)
|
47
|
+
|
48
|
+
rails_zen model act calculator sum
|
49
|
+
|
50
|
+
- When you want to add a method to your model, you could invoke this command.
|
51
|
+
|
52
|
+
- This will get inputs from you such as:
|
53
|
+
- what the method does
|
54
|
+
- the argument names
|
55
|
+
- sample argument with a corresponding output
|
56
|
+
|
57
|
+
- Based on these input, a skeleton method will be written to your model file and model spec file
|
58
|
+
|
59
|
+
*OPTIONS*: If you want to write a class method you can pass --class option like this
|
60
|
+
|
61
|
+
|
62
|
+
rails_zen model g calculator sum --class
|
63
|
+
|
64
|
+
#### Use help to see the examples
|
65
|
+
|
66
|
+
rails_zen model g help
|
67
|
+
rails_zen model act help
|
68
|
+
|
69
|
+
You could see this sample video demonstrating the usage of the gem.
|
70
|
+
|
71
|
+
[![Rails_zen](https://i.ytimg.com/vi/rXphSHFXT1M/0.jpg)](http://youtu.be/rXphSHFXT1M)
|
72
|
+
|
73
|
+
### Tip
|
74
|
+
|
75
|
+
- Create aliases for these commands in your bashrc or zshrc.
|
76
|
+
- I'm using
|
77
|
+
|
78
|
+
alias rzmg="rails_zen model g "
|
79
|
+
alias rzma="rails_zen model act "
|
80
|
+
|
81
|
+
```bash
|
82
|
+
rzmg user name:string score:integer
|
83
|
+
rzma user calculate_score
|
84
|
+
```
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. Fork it ( https://github.com/[my-github-username]/rails_zen/fork )
|
88
|
+
|
89
|
+
bundle binstub rspec-core
|
90
|
+
bundle binstub cucumber
|
91
|
+
|
92
|
+
bin/rspec
|
93
|
+
bin/cucumber
|
94
|
+
|
95
|
+
- This project uses [thor](https://github.com/erikhuda/thor/). You could [refer this blog post](willschenk.com/making-a-command-line-utility-with-gems-and-thor/) to get a quick idea.
|
96
|
+
- To read the source code, start with `lib/cli.rb` & `bin/rails_zen`
|
97
|
+
|
98
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
99
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
100
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
101
|
+
5. Please write unit test using rspec and integeration spec using aruba/cucumber.
|
102
|
+
6. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/rails_zen
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
Feature: Create a function & related spec for the model
|
2
|
+
|
3
|
+
Scenario: Enters the command with arguments
|
4
|
+
When I run `rails_zen model act calculator sum` interactively
|
5
|
+
When I close the stdin stream
|
6
|
+
Then the output should contain "What does your method do?"
|
7
|
+
|
8
|
+
Scenario: Enters what the method does
|
9
|
+
When I run `rails_zen model act calculator sum` interactively
|
10
|
+
And I type "returns sum of two numbers"
|
11
|
+
#And I type "a,b"
|
12
|
+
#And I type "1,2"
|
13
|
+
#And I type "3"
|
14
|
+
When I close the stdin stream
|
15
|
+
Then the output should contain "What name would you give your arguments"
|
16
|
+
|
17
|
+
Scenario: Enters the argument names
|
18
|
+
When I run `rails_zen model act calculator sum` interactively
|
19
|
+
And I type "returns sum of two numbers"
|
20
|
+
And I type "a,b"
|
21
|
+
#And I type "1,2"
|
22
|
+
#And I type "3"
|
23
|
+
When I close the stdin stream
|
24
|
+
Then the output should contain "Give example arguments"
|
25
|
+
|
26
|
+
Scenario: Enters the argument values
|
27
|
+
When I run `rails_zen model act calculator sum` interactively
|
28
|
+
And I type "returns sum of two numbers"
|
29
|
+
And I type "a,b"
|
30
|
+
And I type "1,2"
|
31
|
+
#And I type "3"
|
32
|
+
When I close the stdin stream
|
33
|
+
Then the output should contain "Enter the expected output for the previously entered arguments. eg: 3"
|
34
|
+
|
35
|
+
Scenario: Enters no arguments
|
36
|
+
When I run `rails_zen model act greet hello` interactively
|
37
|
+
And I type "says hello"
|
38
|
+
And I type ""
|
39
|
+
When I close the stdin stream
|
40
|
+
Then the output should not contain "Give example arguments"
|
41
|
+
|
42
|
+
#@focus
|
43
|
+
#Scenario: Enters the end result
|
44
|
+
#When I run `rails_zen model act user sum` interactively
|
45
|
+
#And I type "returns sum of two numbers"
|
46
|
+
#And I type "a,b"
|
47
|
+
#And I type "1,2"
|
48
|
+
#And I type "3"
|
49
|
+
#Then For this user model, the exit status should be 0
|
@@ -0,0 +1,64 @@
|
|
1
|
+
Feature: Generate model related things
|
2
|
+
|
3
|
+
Scenario: Enters the command with arguments
|
4
|
+
When I run `rails_zen model g user name:string` interactively
|
5
|
+
And I type "0"
|
6
|
+
When I close the stdin stream
|
7
|
+
Then the output should contain "0 name"
|
8
|
+
|
9
|
+
Scenario: Selects simple attributes
|
10
|
+
When I run `rails_zen model g user name:string phone:integer` interactively
|
11
|
+
And I type "0"
|
12
|
+
And I type "n"
|
13
|
+
When I close the stdin stream
|
14
|
+
Then the output should contain "Should :phone be present always in your record?"
|
15
|
+
|
16
|
+
Scenario: No unique attributes and integer
|
17
|
+
When I run `rails_zen model g user name:string phone:integer` interactively
|
18
|
+
And I type "0"
|
19
|
+
And I type "n"
|
20
|
+
And I type " "
|
21
|
+
When I close the stdin stream
|
22
|
+
Then the output should contain "phone is an integer do you want to check"
|
23
|
+
|
24
|
+
Scenario: No unique attributes, integer and has a relation
|
25
|
+
When I run `rails_zen model g user name:string` interactively
|
26
|
+
And I type "0"
|
27
|
+
And I type "n"
|
28
|
+
And I type "posts"
|
29
|
+
When I close the stdin stream
|
30
|
+
#Then the exit status should be 0
|
31
|
+
Then the output should contain "Do you have any has_many relations?"
|
32
|
+
|
33
|
+
#@focus
|
34
|
+
# file writing part
|
35
|
+
#Scenario: No unique attributes, integer and has a relation
|
36
|
+
#When I run `rails_zen model g user name:string phone:integer` interactively
|
37
|
+
#And I type "1"
|
38
|
+
#And I type "n"
|
39
|
+
#And I type "posts"
|
40
|
+
#Then the exit status should be 0
|
41
|
+
|
42
|
+
|
43
|
+
Scenario: No unique attributes and string
|
44
|
+
When I run `rails_zen model g user name:string phone:integer` interactively
|
45
|
+
And I type "1"
|
46
|
+
And I type "n"
|
47
|
+
And I type " "
|
48
|
+
Then the exit status should be 0
|
49
|
+
|
50
|
+
Scenario: not a unique attribute and a relation
|
51
|
+
When I run `rails_zen model g user name:string phone:integer location:belongs_to` interactively
|
52
|
+
And I type "0,1"
|
53
|
+
And I type "y"
|
54
|
+
Given I have all files
|
55
|
+
And I type "0"
|
56
|
+
Then the output should contain "0 if it is not unique"
|
57
|
+
|
58
|
+
Scenario: unique attribute is a relation
|
59
|
+
When I run `rails_zen model g user name:string phone:integer location:belongs_to` interactively
|
60
|
+
And I type "0,1"
|
61
|
+
And I type "y"
|
62
|
+
Given I have all files
|
63
|
+
And I type "1"
|
64
|
+
Then the output should contain "0 if it is not unique"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rails_zen/write_to_files/write_to_model'
|
2
|
+
|
3
|
+
Then /^For this (\w+) model, the exit status should be (\d+)$/ do |model, exit_status|
|
4
|
+
#File.open("app/models/#{model}.rb", 'w+') {|f| f.write("class #{model.capitalize} < ActiveRecord::Base\nend\n") }
|
5
|
+
assert_exit_status(exit_status.to_i)
|
6
|
+
end
|
7
|
+
|
8
|
+
Given /I have all files/ do
|
9
|
+
file = String.new("class User < ActiveRecord::Base\nend\n")
|
10
|
+
loc = double('file')
|
11
|
+
|
12
|
+
allow(File).to receive(:open).with(any_args) { loc }
|
13
|
+
allow(File).to receive(:binread).with(any_args) { file }
|
14
|
+
|
15
|
+
allow_any_instance_of(RailsZen::WriteToModel).to receive(:file_name) { '/randompath/yo'}
|
16
|
+
|
17
|
+
allow(Dir).to receive(:glob).with(any_args) {["2023_create_users.rb"]}
|
18
|
+
end
|
data/lib/cli.rb
ADDED
data/lib/cli/model.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "rails_zen/given_model_gen"
|
2
|
+
require "rails_zen/model_action"
|
3
|
+
|
4
|
+
module RailsZen
|
5
|
+
module CLI
|
6
|
+
class Model < Thor
|
7
|
+
desc "g MODELNAME ATTRIBUTES", "generate model, migration, spec files and step & step validations"
|
8
|
+
long_desc %{
|
9
|
+
|
10
|
+
Eg: rails_zen g model user name:string email:string score:integer
|
11
|
+
|
12
|
+
The command generates the usual model, migration and model_spec files. After that,
|
13
|
+
things we manually add such as validation or uniqueness are interactively asked by
|
14
|
+
this command to write into model, migration and spec file.
|
15
|
+
|
16
|
+
|
17
|
+
}
|
18
|
+
def g(model_name, *attrs)
|
19
|
+
attrs = attrs.join(' ')
|
20
|
+
system("rails g model #{model_name} #{attrs}")
|
21
|
+
RailsZen::GivenModelGen.new(model_name, attrs).step_by_step
|
22
|
+
|
23
|
+
#check_has_many
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "act MODELNAME NAME ", "create an actions and action spec for a model"
|
27
|
+
option :class
|
28
|
+
def act(model_name, action_name)
|
29
|
+
RailsZen::ModelAction.new(action_name, options[:class], model_name).write!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rails_zen.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'highline/import'
|
3
|
+
|
4
|
+
module RailsZen
|
5
|
+
class ChosenAttr
|
6
|
+
attr_accessor :name, :type, :validator, :type_based_validators, :scope_attr
|
7
|
+
|
8
|
+
def initialize(name, type)
|
9
|
+
@name = name
|
10
|
+
@type = type
|
11
|
+
@scope_attr = []
|
12
|
+
end
|
13
|
+
def get_user_inputs
|
14
|
+
get_presence_req
|
15
|
+
get_type_based_validations
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_presence_req
|
19
|
+
say "\n\nShould :#{name} be present always in your record?\n"
|
20
|
+
say"--------------------------------------------------------------"
|
21
|
+
inp = agree("Reply with y or n")
|
22
|
+
|
23
|
+
if inp
|
24
|
+
@validator = "validates_presence_of"
|
25
|
+
#say "What should be the default value? If there is no default value enter n"
|
26
|
+
#val = $stdin.gets.strip
|
27
|
+
#if val != 'n'
|
28
|
+
#@default_value = val
|
29
|
+
#end
|
30
|
+
get_uniqueness_req
|
31
|
+
else
|
32
|
+
@validator = nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_uniqueness_req
|
37
|
+
say "Should :#{name} be an unique column?\n"
|
38
|
+
say "-------------------------------------\n\n"
|
39
|
+
say "Reply with \n
|
40
|
+
0 if it is not unique \n
|
41
|
+
1 if it is just unique \n
|
42
|
+
2 if it is unique with respect to another attr \n\n"
|
43
|
+
|
44
|
+
inp = ask("Please enter", Integer) { |q| q.in = 0..2 }
|
45
|
+
|
46
|
+
if inp == 2
|
47
|
+
#say "Setting presence true in your models and migrations"
|
48
|
+
say "\n#{name} is unique along with ?\n Reply with attr name\n "
|
49
|
+
|
50
|
+
if is_relation?
|
51
|
+
@scope_attr << "#{name}_id" unless name.end_with? "_id"
|
52
|
+
end
|
53
|
+
|
54
|
+
say("if it is a relation reply along with id: eg: user_id \n\n $->")
|
55
|
+
@scope_attr << ask("Enter (comma sep list) ", lambda { |str| str.split(/,\s*/) })
|
56
|
+
@scope_attr = @scope_attr.flatten.map(&:to_sym)
|
57
|
+
|
58
|
+
@validator = "validates_uniqueness_scoped_to"
|
59
|
+
elsif inp == 1
|
60
|
+
@validator = "validates_uniqueness_of"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_type_based_validations
|
65
|
+
if(type == "integer" || type == "decimal")
|
66
|
+
@validator_line = "#@validator_line, numericality: true"
|
67
|
+
|
68
|
+
say "#{name} is an integer do you want to check \n
|
69
|
+
1 just the numericality? \n
|
70
|
+
2 check if it is only integer\n\n $->
|
71
|
+
"
|
72
|
+
input = ask("Please enter", Integer) { |q| q.in = 1..2}
|
73
|
+
|
74
|
+
map_input = {
|
75
|
+
1 => "validate_numericality", 2 => "validate_integer"
|
76
|
+
#"3" => "validate_greater_than", "4" => "validate_lesser_than"
|
77
|
+
}
|
78
|
+
|
79
|
+
@type_based_validators = map_input[input]
|
80
|
+
|
81
|
+
elsif(is_relation?)
|
82
|
+
@type_based_validators = "validate_belongs_to"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
def is_relation?
|
86
|
+
type =="belongs_to" || type == "references" || (type.end_with? "_id")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|