attributes_dsl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,219 @@
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
+ - NEW - for adding new features, or backward-compatible changes;
17
+ - CHANGE - for backward-incompatible changes;
18
+ - BUG FIX - for fixing bugs;
19
+ - INTERNAL - for other changes not affecting the API, including changes in documentaton, metrics etc.;
20
+ - VERSION - for version changes.
21
+
22
+ * Always separate commits of different types.
23
+
24
+ * Try to separate various features from each other.
25
+
26
+ * Include unit tests to the same commit as the code. Ensure the code is 100% covered (use mutant!)
27
+
28
+ * Run all tests before making a commit.
29
+ Never ever commit the code that breaks unit tests.
30
+
31
+ * Use metric (run `rake check`) before making a commit.
32
+
33
+ * Do refactoring before making a commit. Best writing is rewriting.
34
+
35
+ * Follow semantic versioning.
36
+
37
+ http://semver.org/
38
+
39
+ * For versions name the commit after a version number, following the pattern:
40
+
41
+ VERSION 1.0.0-rc2
42
+
43
+
44
+ == Formatting:
45
+
46
+ * Use UTF-8. Declare encoding in the first line of every file.
47
+
48
+ # encoding: utf-8
49
+
50
+ * For every new class or method add comment with your name and email.
51
+
52
+ # @author John Johnes <john.johnes@example.com>
53
+
54
+ This is necessary for others could send you they changes to review.
55
+
56
+ * Use 2 space indent, no tabs.
57
+
58
+ * Use Unix-style line endings.
59
+
60
+ * Use spaces around operators, after commas, colons and semicolons,
61
+ around { and before }.
62
+
63
+ * No spaces after (, [ and before ], ).
64
+
65
+ * Align `when` and `else` with `case`.
66
+
67
+ * Use an empty line before the return value of a method (unless it
68
+ only has one line), and an empty line between defs.
69
+
70
+ * Use empty lines to break up a long method into logical paragraphs.
71
+
72
+ * Keep lines fewer than 80 characters.
73
+
74
+ * Strip trailing whitespace.
75
+
76
+
77
+ == Syntax:
78
+
79
+ * Write for the earliest version supported by the gem.
80
+
81
+ * Use double quotes
82
+
83
+ http://viget.com/extend/just-use-double-quoted-ruby-strings
84
+
85
+ * Use def with parentheses when there are arguments.
86
+
87
+ * Never use for, unless you exactly know why.
88
+
89
+ * Never use then, except in case statements.
90
+
91
+ * Use when x then ... for one-line cases.
92
+
93
+ * Use &&/|| for boolean expressions, and/or for control flow. (Rule of thumb: If you have to use outer parentheses, you are using the wrong operators.)
94
+
95
+ * Avoid double negation (!!), unless Null Objects are expected.
96
+
97
+ http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness
98
+
99
+ * Avoid multiline ?:, use if.
100
+
101
+ * Use {...} when defining blocks on one line. Use do...end for multiline blocks.
102
+
103
+ * Avoid return where not required.
104
+
105
+ * Use ||= freely.
106
+
107
+ * Use OO regexps, and avoid =~ $0-9, $~, $` and $' when possible.
108
+
109
+ * Do not use Enumerable#inject when the "memo" object does not change between iterations, use Enumerable#each_with_object instead.
110
+
111
+ * Prefer `fetch` to `[]` syntax. Prefer block syntax to the second argument of `fetch`.
112
+
113
+
114
+ == Naming:
115
+
116
+ * Use snake_case for methods.
117
+
118
+ * Use CamelCase for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.)
119
+
120
+ * Use SCREAMING_SNAKE_CASE for other constants.
121
+
122
+ * Do not use single letter variable names. Avoid uncommunicative names.
123
+
124
+ * Use consistent variable names. Try to keep the variable names close to the object class name.
125
+
126
+ * Use names prefixed with _ for unused variables.
127
+
128
+ * When defining a predicate method that compares against another object of a similar type, name the argument "other".
129
+
130
+ * Prefer `map` over `collect`, `detect` over `find`, `select` over `find_all`.
131
+
132
+ * Prefer `def self.method` to singleton methods.
133
+
134
+ * Avoid alias when alias_method will do.
135
+
136
+
137
+ == Comments:
138
+
139
+ * Use YARD and its conventions for API documentation. Don't put an empty line between the comment block and the def.
140
+
141
+ * Comments longer than a word are capitalized and use punctuation. Use one space after periods.
142
+
143
+ * Avoid superfluous comments.
144
+
145
+
146
+ == Code structuring:
147
+
148
+ * Break code into packages, decoupled from the environment.
149
+
150
+ * Wrap packages into gems.
151
+
152
+ * Inject dependencies explicitly. Leave all outer references on the border of any package. Inside the package use internal references only.
153
+
154
+ * Follow SOLID principles.
155
+
156
+ http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
157
+
158
+ * Only give a method one purpose for existing.
159
+
160
+ If you pass in a boolean to a method, what you're saying is that this method has two different behaviours. Just split it into two single purpose methods.
161
+
162
+ If you have to use the words "AND" or "OR" to describe what the method does it probably does too much.
163
+
164
+ * Avoid long methods. Try to keep them at no more than 6 lines long, and preferably 4 or less.
165
+
166
+ If sections of a method are logically separate by blank lines, then that's probably a sign that those sections should be split into separate methods.
167
+
168
+ * Avoid hashes-as-optional-parameters. Does the method do too much?
169
+
170
+ * Avoid long parameter lists.
171
+
172
+ * Add "global" methods to Kernel (if you have to) and make them private.
173
+
174
+ * Use OptionParser for parsing complex command line options and ruby -s for trivial command line options.
175
+
176
+ * Avoid needless metaprogramming.
177
+
178
+
179
+ == General:
180
+
181
+ * Code in a functional way, avoid mutation when it makes sense.
182
+
183
+ * Always freeze objects assigned to constants.
184
+
185
+ Freeze instances at the end of the `#initializer` method. Don't mutate the state of the instance after initialization.
186
+
187
+ Use either `deep_nine` or `adamantium` gems to make the object deeply frozen.
188
+
189
+ * Do not mutate arguments unless that is the purpose of the method.
190
+
191
+ * Try to have methods either return the state of the object and have
192
+ no side effects, or return self and have side effects. This is
193
+ otherwise known as Command-query separation (CQS):
194
+
195
+ http://en.wikipedia.org/wiki/Command-query_separation
196
+
197
+ * Try following TRUE heuristics by Sandi Metz
198
+
199
+ http://designisrefactoring.com/2015/02/08/introducing-sandi-metz-true/
200
+
201
+ * Do not mess around in core classes when writing libraries. Namespace your code inside the modules, or wrap core classes to decorators of your own.
202
+
203
+ * Do not program defensively.
204
+
205
+ http://www.erlang.se/doc/programming_rules.shtml#HDR11
206
+
207
+ * Keep the code simple.
208
+
209
+ * Don't overdesign.
210
+
211
+ * Don't underdesign.
212
+
213
+ * Avoid bugs.
214
+
215
+ * Read other style guides and apply the parts that don't dissent with this list.
216
+
217
+ * Be consistent.
218
+
219
+ * 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: 8
@@ -0,0 +1,14 @@
1
+ ---
2
+ folders: # The list of folders to be used by any metric.
3
+ - lib
4
+ metrics: # The list of allowed metrics. The other metrics are disabled.
5
+ - cane
6
+ - churn
7
+ - flay
8
+ - flog
9
+ - reek
10
+ - roodi
11
+ - saikuro
12
+ format: html
13
+ output: tmp/metric_fu
14
+ verbose: false
@@ -0,0 +1 @@
1
+ ---
@@ -0,0 +1,24 @@
1
+ ---
2
+ AssignmentInConditionalCheck:
3
+ CaseMissingElseCheck:
4
+ ClassLineCountCheck:
5
+ line_count: 100
6
+ ClassNameCheck:
7
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
8
+ ClassVariableCheck:
9
+ CyclomaticComplexityBlockCheck:
10
+ complexity: 3
11
+ CyclomaticComplexityMethodCheck:
12
+ complexity: 4
13
+ EmptyRescueBodyCheck:
14
+ ForLoopCheck:
15
+ MethodLineCountCheck:
16
+ line_count: 6
17
+ MethodNameCheck:
18
+ pattern: !ruby/regexp /^[\||\^|\&|\!]$|^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
19
+ ModuleLineCountCheck:
20
+ line_count: 100
21
+ ModuleNameCheck:
22
+ pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
23
+ ParameterNumberCheck:
24
+ parameter_count: 4
@@ -0,0 +1,72 @@
1
+ ---
2
+ # settings added by the 'hexx-suit' module
3
+ # output: "tmp/rubocop"
4
+ # format: "html"
5
+
6
+ AllCops:
7
+ Exclude:
8
+ - '**/db/schema.rb'
9
+
10
+ Lint/HandleExceptions:
11
+ Exclude:
12
+ - '**/*_spec.rb'
13
+
14
+ Lint/RescueException:
15
+ Exclude:
16
+ - '**/*_spec.rb'
17
+
18
+ Style/AccessorMethodName:
19
+ Exclude:
20
+ - '**/*_spec.rb'
21
+
22
+ Style/AsciiComments:
23
+ Enabled: false
24
+
25
+ Style/ClassAndModuleChildren:
26
+ Enabled: false
27
+
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ Style/EmptyLinesAroundBlockBody:
32
+ Enabled: false
33
+
34
+ Style/EmptyLinesAroundClassBody:
35
+ Enabled: false
36
+
37
+ Style/EmptyLinesAroundMethodBody:
38
+ Enabled: false
39
+
40
+ Style/EmptyLinesAroundModuleBody:
41
+ Enabled: false
42
+
43
+ Style/EmptyLineBetweenDefs:
44
+ Enabled: false
45
+
46
+ Style/FileName:
47
+ Enabled: false
48
+
49
+ Style/RaiseArgs:
50
+ EnforcedStyle: compact
51
+
52
+ Style/SingleLineMethods:
53
+ Exclude:
54
+ - '**/*_spec.rb'
55
+
56
+ Style/SingleSpaceBeforeFirstArg:
57
+ Enabled: false
58
+
59
+ Style/SpecialGlobalVars:
60
+ Exclude:
61
+ - '**/Gemfile'
62
+ - '**/*.gemspec'
63
+
64
+ Style/StringLiterals:
65
+ EnforcedStyle: double_quotes
66
+
67
+ Style/StringLiteralsInInterpolation:
68
+ EnforcedStyle: double_quotes
69
+
70
+ Style/TrivialAccessors:
71
+ Exclude:
72
+ - '**/*_spec.rb'
@@ -0,0 +1,3 @@
1
+ ---
2
+ warn_cyclo: 4
3
+ error_cyclo: 6
@@ -0,0 +1,6 @@
1
+ ---
2
+ output: tmp/coverage
3
+ filters: # The list of paths to be excluded from coverage checkup
4
+ - "spec/"
5
+ - "config/"
6
+ groups: []
@@ -0,0 +1,37 @@
1
+ ---
2
+ # Settings added by the 'hexx-suit' gem
3
+ output: "tmp/yardstick/output.log"
4
+ path: "lib/**/*.rb"
5
+ rules:
6
+ ApiTag::Presence:
7
+ enabled: true
8
+ exclude: []
9
+ ApiTag::Inclusion:
10
+ enabled: true
11
+ exclude: []
12
+ ApiTag::ProtectedMethod:
13
+ enabled: true
14
+ exclude: []
15
+ ApiTag::PrivateMethod:
16
+ enabled: false
17
+ exclude: []
18
+ ExampleTag:
19
+ enabled: true
20
+ exclude: []
21
+ ReturnTag:
22
+ enabled: true
23
+ exclude: []
24
+ Summary::Presence:
25
+ enabled: true
26
+ exclude: []
27
+ Summary::Length:
28
+ enabled: true
29
+ exclude: []
30
+ Summary::Delimiter:
31
+ enabled: true
32
+ exclude: []
33
+ Summary::SingleLine:
34
+ enabled: true
35
+ exclude: []
36
+ threshold: 100
37
+ verbose: false
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ require "equalizer"
4
+ require "ice_nine"
5
+
6
+ # Simple DSL for PORO attributes
7
+ #
8
+ # @api public
9
+ #
10
+ # @author Andrew Kozin <Andrew.Kozin@gmail.com>
11
+ #
12
+ module AttributesDSL
13
+
14
+ require_relative "attributes_dsl/attribute"
15
+ require_relative "attributes_dsl/attributes"
16
+
17
+ # The mutable collection of declared attributes
18
+ #
19
+ # @return [AttributeDSL::Attributes]
20
+ #
21
+ # @api private
22
+ #
23
+ def attributes
24
+ @attributes ||= Attributes.new
25
+ end
26
+
27
+ # Retisters an attribute by name, options and coercer
28
+ #
29
+ # @example
30
+ # class MyClass
31
+ # extend AttributeDSL
32
+ #
33
+ # attribute :foo, required: true do |value|
34
+ # value.to_i % 5
35
+ # end
36
+ #
37
+ # attribute :bar, default: :BAR
38
+ # end
39
+ #
40
+ # @param [#to_sym] name The unique name of the attribute
41
+ # @param [Proc] coercer The proc to coerce values (including the default ones)
42
+ # @param [Hash] options
43
+ #
44
+ # @option options [Boolean] :required
45
+ # Whether the attribute should be required by the +initializer+
46
+ # This option is ignored (set to +false+) when default value is provided
47
+ # @option options [Object] :default
48
+ # The default value for the attribute
49
+ #
50
+ # @return [undefined]
51
+ #
52
+ def attribute(name, options = {}, &coercer)
53
+ s_name = name.to_sym
54
+ @attributes = attributes.register(s_name, options, &coercer)
55
+
56
+ define_method(s_name) { attributes.fetch(s_name) }
57
+ end
58
+
59
+ # Object contstructor that filters hash of attributes
60
+ #
61
+ # @param [Hash] hash The hash of attributes to be assinged
62
+ #
63
+ # @return [Object]
64
+ #
65
+ # @raise [ArgumentError] in case a required attribute is missed
66
+ #
67
+ def new(hash)
68
+ super attributes.extract(hash)
69
+ end
70
+
71
+ # @private
72
+ def self.extended(klass)
73
+ # use __send__ for compatibility to 1.9.3 (where `.include` was private)
74
+ klass.__send__(:include, InstanceMethods)
75
+ end
76
+
77
+ # Defines instance methods for the hash of attributes and its initializer
78
+ module InstanceMethods
79
+
80
+ # @!attribute [r] attributes
81
+ #
82
+ # @return [Hash] the hash of initialized attributes
83
+ #
84
+ attr_reader :attributes
85
+
86
+ # Initializes the object and sets the hash of its [#attributes]
87
+ #
88
+ # Uses attributes prepared by [.new]
89
+ #
90
+ # @param [Hash] attributes
91
+ #
92
+ def initialize(attributes)
93
+ @attributes = attributes
94
+ end
95
+
96
+ end # module InstanceMethods
97
+
98
+ end # module AttributesDSL