abstract_mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +9 -0
  4. data/.metrics +9 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +2 -0
  7. data/.travis.yml +19 -0
  8. data/.yardopts +3 -0
  9. data/CHANGELOG.md +3 -0
  10. data/Gemfile +9 -0
  11. data/Guardfile +14 -0
  12. data/LICENSE +21 -0
  13. data/README.md +239 -0
  14. data/Rakefile +34 -0
  15. data/abstract_mapper.gemspec +26 -0
  16. data/config/metrics/STYLEGUIDE +230 -0
  17. data/config/metrics/cane.yml +5 -0
  18. data/config/metrics/churn.yml +6 -0
  19. data/config/metrics/flay.yml +2 -0
  20. data/config/metrics/metric_fu.yml +15 -0
  21. data/config/metrics/reek.yml +1 -0
  22. data/config/metrics/roodi.yml +24 -0
  23. data/config/metrics/rubocop.yml +76 -0
  24. data/config/metrics/saikuro.yml +3 -0
  25. data/config/metrics/simplecov.yml +6 -0
  26. data/config/metrics/yardstick.yml +37 -0
  27. data/lib/abstract_mapper/branch.rb +110 -0
  28. data/lib/abstract_mapper/builder.rb +84 -0
  29. data/lib/abstract_mapper/commands.rb +71 -0
  30. data/lib/abstract_mapper/dsl.rb +62 -0
  31. data/lib/abstract_mapper/errors/unknown_command.rb +25 -0
  32. data/lib/abstract_mapper/errors/wrong_node.rb +23 -0
  33. data/lib/abstract_mapper/errors/wrong_rule.rb +23 -0
  34. data/lib/abstract_mapper/functions.rb +76 -0
  35. data/lib/abstract_mapper/node.rb +76 -0
  36. data/lib/abstract_mapper/optimizer.rb +48 -0
  37. data/lib/abstract_mapper/pair_rule.rb +66 -0
  38. data/lib/abstract_mapper/rspec.rb +7 -0
  39. data/lib/abstract_mapper/rule.rb +52 -0
  40. data/lib/abstract_mapper/rules.rb +61 -0
  41. data/lib/abstract_mapper/settings.rb +95 -0
  42. data/lib/abstract_mapper/sole_rule.rb +58 -0
  43. data/lib/abstract_mapper/version.rb +9 -0
  44. data/lib/abstract_mapper.rb +82 -0
  45. data/lib/rspec/functions.rb +25 -0
  46. data/lib/rspec/mapper.rb +40 -0
  47. data/lib/rspec/nodes.rb +58 -0
  48. data/lib/rspec/rules.rb +59 -0
  49. data/spec/integration/faceter.rb +62 -0
  50. data/spec/integration/mapper_definition_spec.rb +33 -0
  51. data/spec/integration/rspec_examples_spec.rb +77 -0
  52. data/spec/spec_helper.rb +20 -0
  53. data/spec/unit/abstract_mapper/branch_spec.rb +126 -0
  54. data/spec/unit/abstract_mapper/builder_spec.rb +78 -0
  55. data/spec/unit/abstract_mapper/commands_spec.rb +105 -0
  56. data/spec/unit/abstract_mapper/dsl_spec.rb +82 -0
  57. data/spec/unit/abstract_mapper/errors/unknown_command_spec.rb +21 -0
  58. data/spec/unit/abstract_mapper/errors/wrong_node_spec.rb +21 -0
  59. data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +23 -0
  60. data/spec/unit/abstract_mapper/functions/compact_spec.rb +25 -0
  61. data/spec/unit/abstract_mapper/functions/filter_spec.rb +26 -0
  62. data/spec/unit/abstract_mapper/functions/subclass_spec.rb +66 -0
  63. data/spec/unit/abstract_mapper/node_spec.rb +84 -0
  64. data/spec/unit/abstract_mapper/optimizer_spec.rb +48 -0
  65. data/spec/unit/abstract_mapper/pair_rule_spec.rb +59 -0
  66. data/spec/unit/abstract_mapper/rule_spec.rb +83 -0
  67. data/spec/unit/abstract_mapper/rules_spec.rb +88 -0
  68. data/spec/unit/abstract_mapper/settings_spec.rb +113 -0
  69. data/spec/unit/abstract_mapper/sole_rule_spec.rb +51 -0
  70. data/spec/unit/abstract_mapper_spec.rb +36 -0
  71. metadata +171 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 805663151f746aef76f5fec0a546289ec9d94f22
4
+ data.tar.gz: f6f64a22fe401d9a53d09bc10d0555445f41b66d
5
+ SHA512:
6
+ metadata.gz: 84df16b02fe5e3d555ba1829f2876d97383bee2e1ce6c0ac382b2894339bc429aa0ff5bc39c0b048567e44c7dc1b392a457334dc2e94694692ebbfe967bfc453
7
+ data.tar.gz: 525f8da10ebddb8f46c6448d2b2c679d5621b5e72632c8a7b3b468ed7c5983513bbb6871e747ac2290a8a22a24667e8a42578230d0953b5cbc814071fda3ec9c
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ *.lock
3
+ .bundle/
4
+ .yardoc/
5
+ coverage/
6
+ doc/
7
+ log/
8
+ pkg/
9
+ tmp/
data/.metrics ADDED
@@ -0,0 +1,9 @@
1
+ # Settings for metric_fu and its packages are collected in the `config/metrics`
2
+ # and loaded by the Hexx::Suit::Metrics::MetricFu.
3
+
4
+ begin
5
+ require "hexx-suit"
6
+ Hexx::Suit::Metrics::MetricFu.load
7
+ rescue LoadError
8
+ puts "The 'hexx-suit' gem is not installed"
9
+ end
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ inherit_from: "./config/metrics/rubocop.yml"
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ bundler_args: --without metrics
5
+ rvm:
6
+ - '1.9.3'
7
+ - '2.0'
8
+ - '2.1'
9
+ - '2.2'
10
+ - ruby-head
11
+ - rbx-2 --1.9
12
+ - rbx-2 --2.1
13
+ - jruby-19mode
14
+ - jruby-20mode
15
+ - jruby-head
16
+ matrix:
17
+ allow_failures:
18
+ - rvm: ruby-head
19
+ - rvm: jruby-head
data/.yardopts ADDED
@@ -0,0 +1,3 @@
1
+ --asset LICENSE
2
+ --exclude lib/abstract_mapper/version.rb
3
+ --output doc/api
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.0.1 2015-07-04
2
+
3
+ This is the first published version of the gem.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :metrics do
6
+ gem "hexx-suit", "~> 2.2" if RUBY_ENGINE == "ruby"
7
+ end
8
+
9
+ gem "thread_safe" # Why on earth I need this here?!
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ guard :rspec, cmd: "bundle exec rspec" do
4
+
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+
7
+ watch(%r{^lib/abstract_mapper/(.+)\.rb$}) do |m|
8
+ "spec/unit/abstract_mapper/#{m[1]}_spec.rb"
9
+ end
10
+
11
+ watch("lib/abstract_mapper.rb") { "spec" }
12
+ watch("spec/spec_helper.rb") { "spec" }
13
+
14
+ end # guard :rspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2015 Andrew Kozin (nepalez), andrew.kozin@gmail.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,239 @@
1
+ Abstract Mapper
2
+ ===============
3
+
4
+ [![Gem Version](https://img.shields.io/gem/v/abstract_mapper.svg?style=flat)][gem]
5
+ [![Build Status](https://img.shields.io/travis/nepalez/abstract_mapper/master.svg?style=flat)][travis]
6
+ [![Dependency Status](https://img.shields.io/gemnasium/nepalez/abstract_mapper.svg?style=flat)][gemnasium]
7
+ [![Code Climate](https://img.shields.io/codeclimate/github/nepalez/abstract_mapper.svg?style=flat)][codeclimate]
8
+ [![Coverage](https://img.shields.io/coveralls/nepalez/abstract_mapper.svg?style=flat)][coveralls]
9
+ [![Inline docs](http://inch-ci.org/github/nepalez/abstract_mapper.svg)][inch]
10
+
11
+ [codeclimate]: https://codeclimate.com/github/nepalez/abstract_mapper
12
+ [coveralls]: https://coveralls.io/r/nepalez/abstract_mapper
13
+ [gem]: https://rubygems.org/gems/abstract_mapper
14
+ [gemnasium]: https://gemnasium.com/nepalez/abstract_mapper
15
+ [travis]: https://travis-ci.org/nepalez/abstract_mapper
16
+ [inch]: https://inch-ci.org/github/nepalez/abstract_mapper
17
+
18
+ Abstract syntax tree (AST) for domain-specific ruby mappers, based on the [transproc] gem.
19
+
20
+ No monkey-patching, no mutable instances. 100% [mutant]-covered.
21
+
22
+ [faceter]: https://github.com/nepalez/faceter
23
+ [mutant]: https://github.com/mbj/mutant
24
+ [transproc]: https://github.com/solnic/transproc
25
+
26
+ Installation
27
+ ------------
28
+
29
+ Add this line to your application's Gemfile:
30
+
31
+ ```ruby
32
+ # Gemfile
33
+ gem "abstract_mapper"
34
+ ```
35
+
36
+ Then execute:
37
+
38
+ ```
39
+ bundle
40
+ ```
41
+
42
+ Or add it manually:
43
+
44
+ ```
45
+ gem install abstract_mapper
46
+ ```
47
+
48
+ Usage
49
+ -----
50
+
51
+ The gem provides the metalevel of abstraction for defining specific DSL for mappers.
52
+
53
+ All you need to provide your own **mapper DSL** is:
54
+
55
+ * define DSL *commands* as a nodes, inherited from `AbstractMapper::Branch` and `AbstractMapper::Node`
56
+ * define DSL-specific *optimization rules* for merging consecutive nodes into more efficient ones
57
+
58
+ Let's suppose we need to provide a DSL for mappers, that can rename keys in array of tuples.
59
+ The following example represents an oversimplified version of the [faceter] gem.
60
+
61
+ ### Define transformations (specific nodes of AST)
62
+
63
+ Every node should implement the `#transproc` method that transforms some input data to the output.
64
+
65
+ When you need attributes, assign them via initializer:
66
+
67
+ ```ruby
68
+ require "abstract_mapper"
69
+
70
+ module Faceter
71
+ # The node to define a transformation of every item of the array from input
72
+ class List < AbstractMapper::Branch
73
+ # The `List#super` is already composes subnodes. All you need is to define,
74
+ # how the list should apply that composition to every item of the list
75
+ #
76
+ # Here the transformation from the transproc gem is used
77
+ def transproc
78
+ Transproc::ArrayTransformations[:map_array, super]
79
+ end
80
+ end
81
+
82
+ # The node to define a renaming of key in a tuple
83
+ class Rename < AbstractMapper::Node
84
+ def initialize(key, **options)
85
+ @key = key
86
+ @new_key = options.fetch(:to)
87
+ super
88
+ end
89
+
90
+ def transproc
91
+ Transproc::HashTransformations[:rename_keys, @key => @new_key]
92
+ end
93
+ end
94
+ end
95
+ ```
96
+
97
+ ### Define optimization rules
98
+
99
+ AbstractMapper defines 2 rules `AbstractMapper::SoleRule` and `AbstractMapper::PairRule`. The first one is applicable to every single node to check if it can be optimized by itself, the second one takes two consecutive nodes and either return them unchanged, or merges them into more time-efficient node.
100
+
101
+ For every rule you need to define two methods:
102
+
103
+ * `#optimize?` that defines if the rule is applicable to given node (or pair of nodes)
104
+ * `#optimize` that returns either array of changed nodes, or one node, or nothing when the node(s) should be removed from the tree
105
+
106
+ Use `#nodes` method to access nodes to be optimized. Base class `AbstractMapper::SoleRule` also defines the `#node` method, while `AbstractMapper::PairRule` defines `#left` and `#right` for the corresponding parts of the pair.
107
+
108
+ ```ruby
109
+ module Faceter
110
+ # The empty lists are useless, because they does nothing at all
111
+ class RemoveEmptyLists < AbstractMapper::SoleRule
112
+ def optimize?
113
+ node.is_a?(List) && node.empty?
114
+ end
115
+
116
+ def optimize
117
+ # returns nothing
118
+ end
119
+ end
120
+
121
+ # Two consecutive list branches are not a good solution, because they
122
+ # iterates twice via the same array of items in the mapped data.
123
+ #
124
+ # That's why when we meet two consecutive lists, we have to merge them
125
+ # into the one list, containing subnodes (entries) from both sources.
126
+ class CompactLists < AbstractMapper::PairRule
127
+ def optimize?
128
+ nodes.join(:|) { |n| n.is_a? List }
129
+ end
130
+
131
+ def optimize
132
+ List.new { nodes.map(:entries).flatten }
133
+ end
134
+ end
135
+ end
136
+ ```
137
+
138
+ ### Register commands and rules
139
+
140
+ Now that both the nodes (transformers) and optimization rules are defined, its time to register them for the mapper:
141
+
142
+ ```ruby
143
+ module Faceter
144
+ class Mapper < AbstractMapper
145
+ configure do
146
+ command :list, List
147
+ command :rename, Rename
148
+
149
+ rule RemoveEmptyLists
150
+ rule CompactLists
151
+ end
152
+ end
153
+ end
154
+ ```
155
+
156
+ ### Use the mapper
157
+
158
+ Now we can create a concrete faceter-based mapper, using its DSL:
159
+
160
+ ```ruby
161
+ require "faceter"
162
+
163
+ class MyMapper < Faceter::Mapper
164
+ list do
165
+ rename :foo, to: :bar
166
+ end
167
+
168
+ list do
169
+ # this is useless, but we have a rule just for the case
170
+ end
171
+
172
+ list do
173
+ rename :baz, to: :qux
174
+ end
175
+ end
176
+
177
+ my_mapper = MyMapper.new
178
+
179
+ my_mapper.call [{ foo: :FOO, baz: :FOO }, { foo: :BAZ, baz: :BAZ }]
180
+ # => [{ bar: :FOO, qux: :FOO }, { bar: :BAZ, qux: :BAZ }]
181
+ ```
182
+
183
+ All the rules are applied before initializing `my_mapper`, so the AST will be the following:
184
+
185
+ ```ruby
186
+ my_mapper.tree
187
+ # => <Root <List [<Rename(foo:, to: :bar)>, <Rename(:baz, to: :qux)>]>
188
+ ```
189
+
190
+ Testing
191
+ -------
192
+
193
+ The gem defines a collection of conventional *shared examples* to make [RSpec] tests simple and verbose.
194
+
195
+ See the list of available examples and how to use them in a [wiki page](https://github.com/nepalez/abstract_mapper/wiki/Shared-examples).
196
+
197
+ Links
198
+ -----
199
+
200
+ * [AbstractMapper API] contains some minor details.
201
+ * [Faceter] is an example of rich mapper.
202
+ * [Transproc] is a small gem that converts methods to pure transformers.
203
+ * [ROM] that heavily uses object mappers in its rich datastore adapters.
204
+
205
+ [AbstractMapper API]: http://www.rubydoc.info/gems/abstract_mapper
206
+ [Faceter]: https://github.com/nepalez/faceter
207
+ [Transproc]: https://github.com/solnic/transproc
208
+ [ROM]: http://rom-rb.org
209
+
210
+ Credits
211
+ -------
212
+
213
+ Many thanks to [Piotr Solnica](https://github.com/solnic) and all the [rom](https://gitter.im/rom-rb/chat) and [transproc](https://gitter.im/transproc/chat) contributors for the implementation of the rich data mapper DSL, and for the idea of even more abstract layer.
214
+
215
+ Compatibility
216
+ -------------
217
+
218
+ Tested under rubies [compatible to MRI 1.9.3+](.travis.yml).
219
+
220
+ Uses [RSpec] 3.0+ for testing and [hexx-suit] for dev/test tools collection.
221
+
222
+ [RSpec]: http://rspec.info
223
+ [hexx-suit]: https://github.com/nepalez/hexx-suit
224
+
225
+ Contributing
226
+ ------------
227
+
228
+ * Read the [STYLEGUIDE](config/metrics/STYLEGUIDE)
229
+ * [Fork the project](https://github.com/nepalez/abstract_mapper)
230
+ * Create your feature branch (`git checkout -b my-new-feature`)
231
+ * Add tests for it
232
+ * Commit your changes (`git commit -am '[UPDATE] Add some feature'`)
233
+ * Push to the branch (`git push origin my-new-feature`)
234
+ * Create a new Pull Request
235
+
236
+ License
237
+ -------
238
+
239
+ See the [MIT LICENSE](LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ begin
3
+ require "bundler/setup"
4
+ rescue LoadError
5
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
6
+ exit
7
+ end
8
+
9
+ # Loads bundler tasks
10
+ Bundler::GemHelper.install_tasks
11
+
12
+ # Loads the Hexx::RSpec and its tasks
13
+ begin
14
+ require "hexx-suit"
15
+ Hexx::Suit.install_tasks
16
+ rescue LoadError
17
+ require "hexx-rspec"
18
+ Hexx::RSpec.install_tasks
19
+ end
20
+
21
+ # Sets the Hexx::RSpec :test task to default
22
+ task :default do
23
+ system "bundle exec rspec spec"
24
+ end
25
+
26
+ desc "Runs mutation metric before the first evil being kept"
27
+ task :exhort do
28
+ system "mutant -r ./spec/spec_helper --use rspec AbstractMapper* --fail-fast"
29
+ end
30
+
31
+ desc "Runs mutation metric to view all evils"
32
+ task :mutant do
33
+ system "mutant -r ./spec/spec_helper --use rspec AbstractMapper*"
34
+ end
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "abstract_mapper/version"
3
+
4
+ Gem::Specification.new do |gem|
5
+
6
+ gem.name = "abstract_mapper"
7
+ gem.version = AbstractMapper::VERSION.dup
8
+ gem.author = "Andrew Kozin"
9
+ gem.email = "andrew.kozin@gmail.com"
10
+ gem.homepage = "https://github.com/nepalez/abstract_mapper"
11
+ gem.summary = "AST for ruby mappers"
12
+ gem.description = "The abstract syntax tree for ruby mappers"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
16
+ gem.test_files = Dir["spec/**/*.rb"]
17
+ gem.extra_rdoc_files = Dir["README.md", "LICENSE"]
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.required_ruby_version = ">= 2.1"
21
+
22
+ gem.add_runtime_dependency "transproc", "~> 0.2", "> 0.2.3"
23
+
24
+ gem.add_development_dependency "hexx-rspec", "~> 0.4"
25
+
26
+ end # Gem::Specification
@@ -0,0 +1,230 @@
1
+ = Ruby Style Guide
2
+
3
+ Adapted from Dan Kubb's Ruby Style Guide
4
+ https://github.com/dkubb/styleguide/blob/master/RUBY-STYLE
5
+
6
+ == Commiting:
7
+
8
+ * Write descriptive commit messages, following the pattern:
9
+
10
+ [TYPE] name
11
+
12
+ The message, describing the changes being made
13
+
14
+ * Use the types below to mark commits:
15
+
16
+ - FEATURE - for adding new features, or backward-compatible changes;
17
+ - CHANGE - for backward-incompatible changes;
18
+ - BUG FIX - for fixing bugs;
19
+ - REFACTORING - for other changes of the code not affecting the API;
20
+ - OTHER - for changes in documentaton, metrics etc, not touching the code;
21
+ - VERSION - for version changes.
22
+
23
+ * Always separate commits of different types (such as FEATURE and CHANGE).
24
+
25
+ * Try to separate various features from each other.
26
+
27
+ * Include specification to the same commit as the code.
28
+
29
+ * Run all tests before making a commit.
30
+ Never commit the code that break unit tests.
31
+
32
+ * Use metric (run `rake check`) before making a commit.
33
+
34
+ * Do refactoring before making a commit. Best writing is rewriting.
35
+
36
+ * Follow semantic versioning.
37
+
38
+ http://semver.org/
39
+
40
+ * For versions name the commit after a version number, following the pattern:
41
+
42
+ VERSION 1.0.0-rc2
43
+
44
+
45
+ == Formatting:
46
+
47
+ * Use UTF-8. Declare encoding in the first line of every file.
48
+
49
+ # encoding: utf-8
50
+
51
+ * Use 2 space indent, no tabs.
52
+
53
+ * Use Unix-style line endings.
54
+
55
+ * Use spaces around operators, after commas, colons and semicolons,
56
+ around { and before }.
57
+
58
+ * No spaces after (, [ and before ], ).
59
+
60
+ * Align `when` and `else` with `case`.
61
+
62
+ * Use an empty line before the return value of a method (unless it
63
+ only has one line), and an empty line between defs.
64
+
65
+ * Use empty lines to break up a long method into logical paragraphs.
66
+
67
+ * Keep lines fewer than 80 characters.
68
+
69
+ * Strip trailing whitespace.
70
+
71
+
72
+ == Syntax:
73
+
74
+ * Write for 2.0.
75
+
76
+ * Use double quotes
77
+
78
+ http://viget.com/extend/just-use-double-quoted-ruby-strings
79
+
80
+ * Use def with parentheses when there are arguments.
81
+
82
+ * Never use for, unless you exactly know why.
83
+
84
+ * Never use then, except in case statements.
85
+
86
+ * Use when x then ... for one-line cases.
87
+
88
+ * Use &&/|| for boolean expressions, and/or for control flow. (Rule
89
+ of thumb: If you have to use outer parentheses, you are using the
90
+ wrong operators.)
91
+
92
+ * Avoid double negation (!!), unless Null Objects are expected.
93
+
94
+ http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness
95
+
96
+ * Avoid multiline ?:, use if.
97
+
98
+ * Use {...} when defining blocks on one line. Use do...end for multiline
99
+ blocks.
100
+
101
+ * Avoid return where not required.
102
+
103
+ * Use ||= freely.
104
+
105
+ * Use OO regexps, and avoid =~ $0-9, $~, $` and $' when possible.
106
+
107
+ * Do not use Enumerable#inject when the "memo" object does not change between
108
+ iterations, use Enumerable#each_with_object instead (in ruby 1.9,
109
+ active_support and backports).
110
+
111
+ * Prefer ENV.fetch to ENV[] syntax.
112
+ Prefer block syntax for ENV.fetch to usage of the second argument.
113
+
114
+
115
+ == Naming:
116
+
117
+ * Use snake_case for methods.
118
+
119
+ * Use CamelCase for classes and modules. (Keep acronyms like HTTP,
120
+ RFC, XML uppercase.)
121
+
122
+ * Use SCREAMING_SNAKE_CASE for other constants.
123
+
124
+ * Do not use single letter variable names. Avoid uncommunicative names.
125
+
126
+ * Use consistent variable names. Try to keep the variable names close
127
+ to the object class name.
128
+
129
+ * Use names prefixed with _ for unused variables.
130
+
131
+ * When defining a predicate method that compares against another object of
132
+ a similar type, name the argument "other".
133
+
134
+ * Prefer map over collect, detect over find, select over find_all.
135
+
136
+ * Use def self.method to define singleton methods.
137
+
138
+ * Avoid alias when alias_method will do.
139
+
140
+
141
+ == Comments:
142
+
143
+ * Use YARD and its conventions for API documentation. Don't put an
144
+ empty line between the comment block and the def.
145
+
146
+ * Comments longer than a word are capitalized and use punctuation.
147
+ Use one space after periods.
148
+
149
+ * Avoid superfluous comments.
150
+
151
+
152
+ == Code structuring:
153
+
154
+ * Break code into packages, decoupled from the environment.
155
+
156
+ * Wrap packages into gems.
157
+
158
+ * Inject dependencies explicitly.
159
+ Leave all outer references on the border of any package. Inside
160
+ the package use internal references only.
161
+
162
+ * Follow SOLID principles.
163
+
164
+ http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
165
+
166
+ * Only give a method one purpose for existing. If you pass in a boolean
167
+ to a method, what you're saying is that this method has two different
168
+ behaviours. Just split it into two single purpose methods. If you have
169
+ to use the words "AND" or "OR" to describe what the method does it
170
+ probably does too much.
171
+
172
+ * Avoid long methods.
173
+ Try to keep them at no more than 6 lines long, and preferably 4 or less.
174
+
175
+ If sections of a method are logically separate by blank lines, then
176
+ that's probably a sign that those sections should be split into separate
177
+ methods.
178
+
179
+ * Avoid hashes-as-optional-parameters. Does the method do too much?
180
+
181
+ * Avoid long parameter lists.
182
+
183
+ * Add "global" methods to Kernel (if you have to) and make them private.
184
+
185
+ * Use OptionParser for parsing complex command line options and
186
+ ruby -s for trivial command line options.
187
+
188
+ * Avoid needless metaprogramming.
189
+
190
+ * Always freeze objects assigned to constants.
191
+
192
+
193
+ == General:
194
+
195
+ * Code in a functional way, avoid mutation when it makes sense.
196
+
197
+ * Try to have methods either return the state of the object and have
198
+ no side effects, or return self and have side effects. This is
199
+ otherwise known as Command-query separation (CQS):
200
+
201
+ http://en.wikipedia.org/wiki/Command-query_separation
202
+
203
+ * Do not mutate arguments unless that is the purpose of the method.
204
+
205
+ * Try following TRUE heuristics by Sandi Metz
206
+
207
+ http://designisrefactoring.com/2015/02/08/introducing-sandi-metz-true/
208
+
209
+ * Do not mess around in core classes when writing libraries.
210
+ Namespace your code inside the modules, or wrap core classes to
211
+ decorators of your own.
212
+
213
+ * Do not program defensively.
214
+
215
+ http://www.erlang.se/doc/programming_rules.shtml#HDR11
216
+
217
+ * Keep the code simple.
218
+
219
+ * Don't overdesign.
220
+
221
+ * Don't underdesign.
222
+
223
+ * Avoid bugs.
224
+
225
+ * Read other style guides and apply the parts that don't dissent with
226
+ this list.
227
+
228
+ * Be consistent.
229
+
230
+ * Use common sense.
@@ -0,0 +1,5 @@
1
+ ---
2
+ abc_max: "10"
3
+ line_length: "80"
4
+ no_doc: "y"
5
+ no_readme: "y"
@@ -0,0 +1,6 @@
1
+ ---
2
+ ignore_files:
3
+ - spec
4
+ - config
5
+ minimum_churn_count: 0
6
+ start_date: "1 year ago"
@@ -0,0 +1,2 @@
1
+ ---
2
+ minimum_score: 9
@@ -0,0 +1,15 @@
1
+ ---
2
+ folders: # The list of folders to be used by any metric.
3
+ - lib/abstract_mapper.rb
4
+ - lib/abstract_mapper
5
+ metrics: # The list of allowed metrics. The other metrics are disabled.
6
+ - cane
7
+ - churn
8
+ - flay
9
+ - flog
10
+ - reek
11
+ - roodi
12
+ - saikuro
13
+ format: html
14
+ output: tmp/metric_fu
15
+ verbose: false
@@ -0,0 +1 @@
1
+ ---