rails_zen 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,76 @@
1
+ require 'rails_zen/chosen_attr'
2
+ require 'rails_zen/write_to_files'
3
+ require 'highline/import'
4
+
5
+ module RailsZen
6
+ class GivenModelGen
7
+ attr_accessor :name, :raw_attributes, :simple_attributes
8
+
9
+ def initialize(name, raw_attrs)
10
+ @name = name
11
+ @raw_attributes = raw_attrs
12
+ @simple_attributes = []
13
+ end
14
+
15
+
16
+ def step_by_step
17
+ say "\nThese are your attributes"
18
+ say "---------------------------\n"
19
+
20
+ attrs.each_with_index { |attr, i| puts "#{i} #{attr}" }
21
+ say "\n\nChoose the one that don't require 'presence true' or 'validations' or uniqueness.\n Enter like this eg: 0,1. or just enter "
22
+ say "\n----------------------------------\n\n$.> "
23
+
24
+ @simple_attributes = ask("Enter (comma sep list) ", lambda { |str| str.split(/,\s*/) })
25
+
26
+ chosen_attrs.each do |attr_obj|
27
+ attr_obj.get_user_inputs
28
+ RailsZen::WriteToFiles.new(attr_obj, name).write
29
+ end
30
+
31
+ ask_for_has_many_relations
32
+ end
33
+
34
+ def chosen_attrs
35
+
36
+ attr_hash = attrs_with_types
37
+ final_attr_objs = []
38
+ i = -1
39
+ attr_hash.each do |attr, type|
40
+ i += 1
41
+ unless simple_attributes.include? "#{i}"
42
+ final_attr_objs << RailsZen::ChosenAttr.new(attr, type)
43
+ end
44
+ end
45
+ final_attr_objs
46
+ end
47
+
48
+
49
+ def ask_for_has_many_relations
50
+ say "\nDo you have any has_many relations? Enter the name if so, otherwise leave it. eg: posts,comments"
51
+
52
+ @has_many_relations = ask("Enter (comma sep list) ", lambda { |str| str.split(/,\s*/) })
53
+
54
+ @has_many_relations.each do |rel|
55
+
56
+ m = RailsZen::WriteToModel.new
57
+ m.model_name = @name
58
+ m.adding_to_file!(" has_many :#{rel}\n")
59
+
60
+ s = RailsZen::WriteToSpec.new
61
+ s.model_name = @name
62
+ s.adding_to_file!("it { is_expected.to have_many(:#{rel}) }")
63
+ end
64
+
65
+ end
66
+ def attrs
67
+ raw_attributes.scan(/\w+(?=:)/)
68
+ end
69
+ private
70
+ def attrs_with_types
71
+ raw_attributes.scan(/(\w+):(\w+)/).to_h
72
+ end
73
+
74
+
75
+ end
76
+ end
@@ -0,0 +1,106 @@
1
+ require 'rails_zen/write_to_files/write_to_model'
2
+ require 'rails_zen/write_to_files/write_to_spec'
3
+ require 'highline/import'
4
+
5
+ module RailsZen
6
+ class ModelAction
7
+ attr_writer :is_class_action
8
+
9
+ def initialize(name, is_class_action, model)
10
+ @name = name
11
+ @model = model
12
+ @is_class_action = is_class_action
13
+ @arg_names = []
14
+ @args = []
15
+ end
16
+
17
+ def write!
18
+ get_necessary_info
19
+
20
+ m = RailsZen::WriteToModel.new
21
+ m.model_name = @model
22
+ m.adding_to_file!(action_string)
23
+
24
+ s = RailsZen::WriteToSpec.new
25
+ s.model_name = @model
26
+
27
+ unless File.foreach("spec/models/#{@model}_spec.rb").grep(factory_girl_match).any? #check for factory
28
+ s.adding_to_file!(factory_method)
29
+ end
30
+ s.adding_to_file!(action_spec_string)
31
+ end
32
+
33
+ private
34
+
35
+ def factory_girl_match
36
+ Regexp.new("FactoryGirl.create(:#{@model})")
37
+ end
38
+
39
+ def get_necessary_info
40
+ say "What does your method do? (Please don't use 'it' or 'should' in your definition)\n"
41
+ @functionality = ask("Eg: returns sum of 2 numbers\n")
42
+
43
+ say "\n\n------------ARGUMENTS-----------------\n"
44
+
45
+ say "\nWhat name would you give your arguments for the #{@name} method? eg: num1,num2\n"
46
+
47
+ @arg_names = ask("Enter (comma sep) list", lambda { |str| str.split(/,\s*/) })
48
+
49
+ if @arg_names.any?
50
+ say "\nGive example arguments inputs\n"
51
+ @args = ask("Enter (comma sep list). Eg: 1,2 ", lambda { |str| str.split(/,\s*/) })
52
+ end
53
+
54
+
55
+ @expected = ask("Enter the expected output for the previously entered arguments. eg: 3")
56
+ end
57
+
58
+ def action_string
59
+ %{
60
+ def #{method_with_args}
61
+ end
62
+ }
63
+ end
64
+
65
+ def action_spec_string
66
+ if @is_class_action
67
+ %{
68
+ it { is_expected.to respond_to :#{@name}}
69
+
70
+ describe ".#{@name}" do
71
+ it "#{@functionality}" do
72
+ expect(#{@model.capitalize}.#{@name}(#{sample_arguments})).to eq \"#{@expected}\"
73
+ end
74
+ end
75
+
76
+ }
77
+ else
78
+ %{
79
+ describe "##{@name}" do
80
+ it "#{@functionality}" do
81
+ expect(#{@model}.#{@name}(#{sample_arguments})).to eq \"#{@expected}\"
82
+ end
83
+ end
84
+
85
+ }
86
+ end
87
+ end
88
+ def method_with_args
89
+ if @is_class_action
90
+ "self.#{@name}(#{arguments})"
91
+ else
92
+ "#{@name}(#{arguments})"
93
+ end
94
+ end
95
+
96
+ def sample_arguments
97
+ @args.join(", ")
98
+ end
99
+ def arguments
100
+ @arg_names.join(", ")
101
+ end
102
+ def factory_method
103
+ "let(:#{@model}) { FactoryGirl.create(:#{@model}) }"
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,3 @@
1
+ module RailsZen
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'rails_zen/write_to_files/write_to_spec'
2
+ require 'rails_zen/write_to_files/write_to_model'
3
+ require 'rails_zen/write_to_files/write_to_migration'
4
+
5
+ class RailsZen::WriteToFiles
6
+ attr_reader :attr, :model_name
7
+
8
+ def initialize(attr, model_name)
9
+ @attr = attr
10
+ @model_name = model_name
11
+ end
12
+
13
+ def build_file_writers(type)
14
+ # When including thor, could not use initialize hence building it
15
+ Object.const_get("RailsZen::#{type}").new.tap do |w|
16
+ w.name = attr.name
17
+ w.attr_type = attr.type
18
+ w.scope_attr = attr.scope_attr
19
+ w.validator = attr.validator
20
+ w.type_based_validators = attr.type_based_validators
21
+ w.model_name = model_name
22
+ end
23
+ end
24
+
25
+ def write
26
+ ["WriteToSpec", "WriteToMigration", "WriteToModel"].each do |type|
27
+ build_file_writers(type).write!
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,12 @@
1
+ module RailsZen::ModelLeveLValidation
2
+
3
+ def validate_belongs_to
4
+ ""
5
+ end
6
+ def validate_numericality
7
+ ", numericality: true"
8
+ end
9
+ def validate_integer
10
+ ", numericality: { only_integer: true }"
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module RailsZen::ModelLeveLValidationSpec
2
+
3
+ def validate_belongs_to
4
+ "it { is_expected.to belong_to(:#{name}) }"
5
+ end
6
+ def validate_numericality
7
+ "it { is_expected.to validates_numericality_of(:#{name}) }"
8
+ end
9
+ def validate_integer
10
+ "it { is_expected.to validates_numericality_of(:#{name}).only_integer }"
11
+ end
12
+ end
13
+
14
+
@@ -0,0 +1,37 @@
1
+ require "rails_zen/write_to_files/write_to_model"
2
+ require 'active_support/core_ext/string'
3
+
4
+ class RailsZen::WriteToMigration < RailsZen::WriteToModel
5
+
6
+ def write!
7
+ if @validator
8
+ line = send(@validator)
9
+ append_to_line(line)
10
+ end
11
+ if scope_attr.any?
12
+ inject_into_file file_name, "t.index #{scope_attr.to_s}\n", before: "t.timestamps"
13
+ end
14
+ end
15
+ def append_to_line(line)
16
+ gsub_file file_name, /t.#{attr_type}.+#{name}.*$/ do |match|
17
+ match = line
18
+ end
19
+ end
20
+
21
+ def file_name
22
+ Dir.glob("db/migrate/*create_#{@model_name.pluralize}.rb")[0]
23
+ # need to use pluralize here
24
+ end
25
+
26
+ private
27
+ def validates_presence_of
28
+ "t.#{attr_type} :#{name}, required: true, null: false"
29
+ end
30
+ def validates_uniqueness_of
31
+ "t.#{attr_type} :#{name}, required: true, null: false, index: true"
32
+ end
33
+ def validates_uniqueness_scoped_to
34
+ "t.#{attr_type} :#{name}, required: true, null: false, index: true"
35
+ end
36
+ end
37
+
@@ -0,0 +1,57 @@
1
+ require 'thor'
2
+ require "rails_zen/write_to_files/model_level_validation"
3
+
4
+ module RailsZen
5
+ class WriteToModel
6
+
7
+
8
+ attr_accessor :name, :scope_attr, :validator, :type_based_validators, :model_name, :attr_type, :file_name
9
+ include RailsZen::ModelLeveLValidation
10
+ include Thor::Base
11
+ include Thor::Actions
12
+
13
+
14
+ def write!
15
+
16
+ if @validator
17
+ output = send(@validator)
18
+ if type_num?
19
+ type_output = send(@type_based_validators)
20
+ adding_to_file!(" #{output + type_output}\n" )
21
+ else
22
+ adding_to_file!(" #{output}\n")
23
+ end
24
+ end
25
+ end
26
+
27
+ def adding_to_file!(line)
28
+ inject_into_class(file_name, model_name.capitalize, line)
29
+ end
30
+
31
+ def file_name
32
+ "app/models/#{model_name}.rb"
33
+ end
34
+ private
35
+
36
+ def type_num?
37
+ @attr_type == "integer" || @attr_type == "decimal"
38
+ end
39
+ def validates_presence_of
40
+ "validates :#{name}, presence: true"
41
+ end
42
+ def validates_uniqueness_of
43
+ "validates :#{name}, presence: true, uniqueness: true"
44
+ end
45
+ def validates_uniqueness_scoped_to
46
+ "validates_uniqueness_of :#{scope_attr[0]}, scope: #{resolve_scope}"
47
+ end
48
+
49
+ def resolve_scope
50
+ if scope_attr.length == 2
51
+ ":#{scope_attr[1]}"
52
+ else
53
+ scope_attr[1..-1].to_s
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,45 @@
1
+ require "rails_zen/write_to_files/model_level_validation_spec"
2
+ require "rails_zen/write_to_files/write_to_model"
3
+
4
+ class RailsZen::WriteToSpec < RailsZen::WriteToModel
5
+
6
+ include RailsZen::ModelLeveLValidationSpec
7
+
8
+ def write!
9
+ if @validator
10
+ unless File.foreach("spec/models/#{@model_name}_spec.rb").grep(factory_girl_match).any?
11
+ adding_to_file!(factory_method)
12
+ end
13
+ adding_to_file!(send(@validator))
14
+
15
+ end
16
+
17
+ adding_to_file!(send(@type_based_validator)) if @type_based_validator
18
+ end
19
+ def adding_to_file!(output)
20
+ inject_into_file(file_name, " #{output}\n", after: "RSpec.describe #{@model_name.capitalize}, type: :model do\n" )
21
+ end
22
+
23
+ private
24
+ def factory_girl_match
25
+ Regexp.new("FactoryGirl.create(:#{@model_name})")
26
+ end
27
+ def factory_method
28
+ "let(:#{@model_name}) { FactoryGirl.create(:#{@model_name}) }"
29
+ end
30
+
31
+ def file_name
32
+ "spec/models/#{@model_name}_spec.rb"
33
+ end
34
+
35
+ def validates_presence_of
36
+ "it { #{@model_name}; is_expected.to validate_presence_of(:#{name})}"
37
+ end
38
+ def validates_uniqueness_of
39
+ "it { #{@model_name}; is_expected.to validate_uniqueness_of(:#{name})}"
40
+ end
41
+ def validates_uniqueness_scoped_to
42
+ "it { #{@model_name}; is_expected.to validate_uniqueness_of(:#{scope_attr[0]}).scoped_to(#{resolve_scope})}"
43
+ end
44
+
45
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,8 @@
1
+ module MyGem
2
+ class Railtie < Rails::Railtie
3
+ initializer "Include your code in the controller" do
4
+ ActiveSupport.on_load(:action_controller) do
5
+ include MyGem
6
+ end
7
+ end
8
+ end
data/rails_zen.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rails_zen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rails_zen"
8
+ spec.version = RailsZen::VERSION
9
+ spec.authors = ["Vysakh Sreenivasan"]
10
+ spec.email = ["diplomatv@gmail.com"]
11
+ spec.summary = %q{Interactive rails generator generating files (models, migration) and related specs.}
12
+ spec.description = %q{Automate the writing of validations, relations in files and specs. Create boilerplate validation in models, specs, migrations. This specs are generated based on rspec, shoulda-matchers and factorygirl }
13
+ spec.homepage = "http://github.com/vysakh0/rails_zen"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'thor', "~> 0.19"
22
+ spec.add_dependency 'highline', "~> 1.4"
23
+ spec.add_dependency 'activesupport', "~> 4.2"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.7"
26
+ spec.add_development_dependency "aruba", "~> 0.6"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.2"
29
+ end
@@ -0,0 +1,92 @@
1
+ require 'rails_zen/chosen_attr'
2
+
3
+ RSpec.describe RailsZen::ChosenAttr do
4
+
5
+
6
+ subject {
7
+ RailsZen::ChosenAttr.new("name", "string")
8
+ }
9
+
10
+ #after do
11
+ #$stdin = STDIN
12
+ #end
13
+
14
+ it { is_expected.to respond_to :get_user_inputs}
15
+
16
+
17
+ describe "#get_presence_req" do
18
+
19
+ context "when 'y' for presence" do
20
+
21
+ context "when 0 for uniqueness" do
22
+ it "sets validator to validates_presence_of" do
23
+ set_stream(StringIO.new("y\n0\n"))
24
+ subject.get_user_inputs
25
+ expect(subject.validator).to eq "validates_presence_of"
26
+ end
27
+ end
28
+ context "when '1' for uniqueness" do
29
+ it "sets validator to validates_uniqueness_of" do
30
+ set_stream(StringIO.new("y\nr\n1\n"))
31
+ subject.get_user_inputs
32
+ expect(subject.validator).to eq "validates_uniqueness_of"
33
+ end
34
+ end
35
+ context "when '2' for uniqueness" do
36
+ it "sets validator to validates_uniqueness_scoped_to" do
37
+ set_stream(StringIO.new("y\n 2\n order_id\n"))
38
+ subject.get_user_inputs
39
+ expect(subject.validator).to eq "validates_uniqueness_scoped_to"
40
+ end
41
+ end
42
+ end
43
+ context "when n for presence" do
44
+
45
+ fit "sets validator to validates_presence_of" do
46
+ set_stream(StringIO.new("n\n"))
47
+ subject.get_user_inputs
48
+ expect(subject.validator).to be nil
49
+ end
50
+
51
+ end
52
+
53
+ describe "#get_type_based_validations" do
54
+ context "when type is integer" do
55
+
56
+ before do
57
+ @chosen = RailsZen::ChosenAttr.new("phone", "integer")
58
+ end
59
+ context "when just the numericality is chosen" do
60
+ fit "sets type_based_validators to validate_numericality" do
61
+ set_stream(StringIO.new("1\n"))
62
+ @chosen.get_type_based_validations
63
+ expect(@chosen.type_based_validators).to eq "validate_numericality"
64
+ end
65
+ end
66
+ context "when numericality with integer is chosen" do
67
+ it "sets type_based_validators to validate_integer" do
68
+ set_stream(StringIO.new("2\n"))
69
+ @chosen.get_type_based_validations
70
+ expect(@chosen.type_based_validators).to eq "validate_integer"
71
+ end
72
+ end
73
+ end
74
+ context "when type is a relation" do
75
+ before do
76
+ @chosen = RailsZen::ChosenAttr.new("user", "belongs_to")
77
+ end
78
+ it "sets type_based_validators to validate_belongs_to" do
79
+ @chosen.get_type_based_validations
80
+ expect(@chosen.type_based_validators).to eq "validate_belongs_to"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ def set_stream(input)
88
+ #inp = $terminal.instance_variable_get(:@input)
89
+ #inp.flush
90
+ $terminal.instance_variable_set(:@input, input)
91
+ # highline set input, $stdin setting is not working. i.e $stdin = input
92
+ end