like_im_five 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0a15ef4ccf7a86b9607360ca2a49606d3cc46b44ed6c1a3ba716cfc457b58342
4
+ data.tar.gz: 1702a26fc933d3d8eaba0756b4ca54d73b5e662e820da515945ceb4898086e97
5
+ SHA512:
6
+ metadata.gz: a34a78a5856c216f49b64479ba0c154217e1035a888147ac2ff1d5fac1ddd9de76d31153cd6b6ff8b9229e16d42947f4881b22414a62976800dd9679ce275518
7
+ data.tar.gz: 8794426f305605d4ce4b7b2c17649f1d6004803631514ce8309174b6f362445b9bed89f66c5b4efa5d44dfa932a165f9bfb5d8a11ba22ce6452a8b1a706ba44c
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # like_im_five
2
+
3
+ Do you use the awesome [factory_bot gem](https://github.com/thoughtbot/factory_bot) to create your contexts ?
4
+ Have you ever wasted time to set up testing context rather to be focus on the code ?
5
+ Have you ever had pain to write a long context because of unknow associations ?
6
+
7
+ Like Im Five generate a file with factories you need to test a specific object. It use you DB development to retrieve the object you want and all associations you will have need to setup the test.
8
+
9
+ **Create a complex testing context in a few seconds.**
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'like_im_five'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install like_im_five
26
+
27
+ ## Usage
28
+
29
+ Just open you terminal, go in your project and type:
30
+
31
+ `like_im_five id_of_object table_of_object`
32
+
33
+ *(if you are facing somme issue try to prepend **bundle exec** before the commands above)*
34
+
35
+ **It takes two parameters.**
36
+
37
+ `id_of_object`
38
+ The gem use your development database so you have to indicate of which one object you would like create context.
39
+
40
+ `table_of_object`
41
+ Then you have to specify what is the table of the `id` you just typed above.
42
+
43
+ **Example:**
44
+
45
+ In your DB development you have these objects:
46
+
47
+ ```ruby
48
+ => #<DummyApp::User id: 12 name: "Jean", city: "London", age: 20, created_at: "2019-12-30 22:45:33", updated_at: "2019-12-30 22:45:33">
49
+ ```
50
+ ```ruby
51
+ => #<DummyApp::Article id: 1, dummy_app_user_id: 12, dummy_app_category_id: 1, title: "Subway Art 25th", body: "Anniversary Edition", created_at: "2019-12-30 22:45:33", updated_at: "2019-12-30 22:45:33">
52
+ ```
53
+ ```ruby
54
+ => #<DummyApp::Category id: 1, dummy_app_topic_id: 3, label: "Graffiti", created_at: "2019-12-30 22:45:33", updated_at: "2019-12-30 22:45:33">
55
+ ```
56
+ ```ruby
57
+ => #<DummyApp::Topic id: 3, title: "Culture", description: "Culture is beautiful", created_at: "2019-12-30 22:45:33", updated_at: "2019-12-30 22:45:33">
58
+ ```
59
+
60
+ You want to test your `article`, in your terminal you have to type the following command:
61
+
62
+ `like_im_five 1 dummy_app_articles`
63
+
64
+ and it will generate a new file in your `/spec` folder named: `data.txt` containing factories:
65
+
66
+ ```ruby
67
+ let(:dummy_app_article) { create :dummy_app_article, id: 1, dummy_app_user_id: 12, dummy_app_category_id: 1, title: "Subway Art 25th", body: "Anniversary Edition" }
68
+ let(:dummy_app_user) { create :dummy_app_user, id: 12, name: "Jean", city: "London", age: 20 }
69
+ let(:dummy_app_category) { create :dummy_app_category, id: 1, label: "Graffiti", dummy_app_topic_id: 3 }
70
+ let(:dummy_app_topic) { create :dummy_app_topic, id: 3, title: "Culture", description: "Culture is beautiful" }
71
+ ```
72
+
73
+ That's it, just copy/paste it in your concerned spec.
74
+
75
+ ## Corner cases
76
+
77
+ - **UID**
78
+ I you are using `UID` rather than traditional `ID` no worries, we handle it for you. Just type commande below:
79
+
80
+ `like_im_five "ffe-230-opoifhhfru-333" dummy_app_articles`
81
+
82
+ - **Similarity detection to match table name with model**
83
+ For some reason it can be useful to use `Inflection`, especially if you are not coding in english.
84
+
85
+ If you named a table `vitraux` and your model `vitrail` we will match both to build your factory.
86
+
87
+ *nb: if your model name is really to different than your table name it can fails to match.*
88
+
89
+
90
+ ## Contributing
91
+
92
+ Bug reports and pull requests are welcome on GitHub at https://github.com/morissetcl/like_im_five. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/morissetcl/like_im_five/blob/master/CODE_OF_CONDUCT.md).
93
+
94
+
95
+ ## License
96
+
97
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
98
+
99
+ ## Code of Conduct
100
+
101
+ Everyone interacting in the LikeImFive project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/morissetcl/like_im_five/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/like_im_five ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby -wU
2
+ require 'like_im_five'
3
+
4
+ LikeImFive.call(ARGV)
@@ -0,0 +1,23 @@
1
+ require 'rails'
2
+
3
+ class CreateFactory
4
+ class << self
5
+ def call(objects)
6
+ File.open("spec/data.txt", "w+") do |f|
7
+ objects.each do |object|
8
+ f.puts(formatte_factory(object))
9
+ f.puts("\n")
10
+ end
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def formatte_factory(object)
17
+ atttributes_symbolized = object[:attributes][0].inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
18
+ formatted_attributes = atttributes_symbolized.to_s.delete(':').delete('{').delete('}').gsub("=>", ": ")
19
+ factory_name = object[:table].singularize.to_sym
20
+ "let(:#{factory_name}) { create :#{factory_name}, #{formatted_attributes} }"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,57 @@
1
+ require 'rails'
2
+ require "rubygems/text"
3
+ require_relative './create_factory'
4
+
5
+ class ExtractAssociatedObject
6
+ attr_reader :object, :associated_object, :schema_tables
7
+
8
+ def initialize(object, associated_object = [])
9
+ @object = object[0]
10
+ @associated_object = associated_object
11
+ @schema_tables = ActiveRecord::Base.connection.tables
12
+ end
13
+
14
+ def call
15
+ associated_tables_names.each do |table, column|
16
+ value = object[column]
17
+ next if value.nil?
18
+
19
+ result = ActiveRecord::Base.connection.execute("SELECT * FROM #{table} WHERE id='#{value}'").to_a
20
+ result[0].delete('updated_at')
21
+ result[0].delete('created_at')
22
+ associated_object << { table: table, attributes: result }
23
+ ExtractAssociatedObject.new(result, associated_object).call
24
+ end
25
+ CreateFactory.call(associated_object)
26
+ end
27
+
28
+ private
29
+
30
+ def associated_tables_names
31
+ tables_names = []
32
+ object.select do |column|
33
+ next unless column.include?("_id")
34
+
35
+ table = column.split("_id").join.pluralize
36
+ if table_not_exist?(table)
37
+ table = find_closest_table_name(table)
38
+ end
39
+ tables_names << ["#{table}", column]
40
+ end
41
+ tables_names
42
+ end
43
+
44
+ def table_not_exist?(table)
45
+ !schema_tables.include?(table)
46
+ end
47
+
48
+ def find_closest_table_name(table)
49
+ schema_tables.each do |table_name|
50
+ levenshtein = Class.new.extend(Gem::Text).method(:levenshtein_distance)
51
+ similarity = levenshtein.call(table, table_name)
52
+ next if similarity > 3
53
+
54
+ return table_name
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,37 @@
1
+ require 'rails'
2
+ require 'active_record'
3
+ require 'erb'
4
+ require_relative './extract_associated_object'
5
+ require_relative './general_configuration'
6
+
7
+ class ExtractSpecificObject < GeneralConfiguration
8
+ class << self
9
+ def call(id:, table:)
10
+ initialize_configuration
11
+ return table_not_exist(table) unless ActiveRecord::Base.connection.tables.include?(table)
12
+
13
+ result = ActiveRecord::Base.connection.execute("SELECT * FROM #{table} WHERE id='#{id}'").to_a
14
+ return not_found(table, id) if result.blank?
15
+
16
+ remove_timestamps(result)
17
+
18
+ associated_object = [{ table: table, attributes: result }]
19
+ ExtractAssociatedObject.new(result, associated_object).call
20
+ end
21
+
22
+ private
23
+
24
+ def remove_timestamps(result)
25
+ result[0].delete('updated_at')
26
+ result[0].delete('created_at')
27
+ end
28
+
29
+ def not_found(table, id)
30
+ print "Can't find id=#{id} in table=#{table}"
31
+ end
32
+
33
+ def table_not_exist(table)
34
+ print "Table #{table} does not exist in your DB"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ class GeneralConfiguration
2
+ def self.initialize_configuration
3
+ db_config = YAML.load(ERB.new(File.read('./config/database.yml')).result)
4
+ ActiveRecord::Base.establish_connection(db_config['development'])
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module LikeImFive
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "like_im_five/version"
2
+ require "extract_specific_object"
3
+
4
+ module LikeImFive
5
+ class Error < StandardError; end
6
+ def self.call(arg)
7
+ ExtractSpecificObject.call(id: arg[0], table: arg[1])
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: like_im_five
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Clément Morisset
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ description: Like Im Five generate a file with factories you need to test a speific
42
+ object. It use you DB dévelopment to retrieve the object you want and all associations
43
+ you will have need to setup the test.
44
+ email:
45
+ - morissetcl87@gmail.com
46
+ executables:
47
+ - like_im_five
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - README.md
52
+ - Rakefile
53
+ - bin/like_im_five
54
+ - lib/create_factory.rb
55
+ - lib/extract_associated_object.rb
56
+ - lib/extract_specific_object.rb
57
+ - lib/general_configuration.rb
58
+ - lib/like_im_five.rb
59
+ - lib/like_im_five/version.rb
60
+ homepage: https://github.com/morissetcl
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message: Like Im Five installed! Thx.
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.3.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.7.6
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Create a complex testing context in a few seconds.
84
+ test_files: []