concord-0.1.5/0000755000175200017520000000000013631621556012406 5ustar debiandebianconcord-0.1.5/spec/0000755000175200017520000000000013631621556013340 5ustar debiandebianconcord-0.1.5/spec/unit/0000755000175200017520000000000013631621556014317 5ustar debiandebianconcord-0.1.5/spec/unit/concord/0000755000175200017520000000000013631621556015746 5ustar debiandebianconcord-0.1.5/spec/unit/concord/universal_spec.rb0000644000175200017520000000714713631621556021326 0ustar debiandebianrequire 'spec_helper' describe Concord do let(:class_under_test) do Class.new do include Concord.new(:foo, :bar) end end let(:instance_a) { class_under_test.new(foo, bar) } let(:instance_b) { class_under_test.new(foo, bar) } let(:instance_c) { class_under_test.new(foo, double('Baz')) } let(:foo) { double('Foo') } let(:bar) { double('Bar') } context 'initializer lines' do it 'creates a private #initialize method' do mod = Module.new expect { mod.send(:include, Concord.new) } .to change { mod.private_method_defined?(:initialize) } .from(false).to(true) end it 'creates an initializer that asserts the number of arguments' do expect { class_under_test.new(1) } .to raise_error(ArgumentError, 'wrong number of arguments (1 for 2)') end it 'creates an initializer that allows 2 arguments' do expect { class_under_test.new(1, 2) }.to_not raise_error end it 'creates an initializer that is callable via super' do class_under_test.class_eval do attr_reader :baz public :foo public :bar def initialize(foo, bar) @baz = foo + bar super(foo, bar) end end instance = class_under_test.new(1, 2) expect(instance.foo).to eql(1) expect(instance.bar).to eql(2) expect(instance.baz).to eql(3) end it 'creates an initializer that is callable via zsuper' do class_under_test.class_eval do attr_reader :baz public :foo public :bar def initialize(foo, bar) @baz = foo + bar super end end instance = class_under_test.new(1, 2) expect(instance.foo).to eql(1) expect(instance.bar).to eql(2) expect(instance.baz).to eql(3) end it 'creates an initializer that sets the instance variables' do instance = class_under_test.new(1, 2) expect(instance.instance_variable_get(:@foo)).to be(1) expect(instance.instance_variable_get(:@bar)).to be(2) end end context 'with no objects to compose' do it 'assigns no ivars' do instance = Class.new { include Concord.new }.new expect(instance.instance_variables).to be_empty end end context 'visibility' do it 'should set attribute readers to protected' do protected_methods = class_under_test.protected_instance_methods expect(protected_methods).to match_array([:foo, :bar]) end end context 'attribute behavior' do subject { instance_a } specify { expect(subject.send(:foo)).to be(foo) } specify { expect(subject.send(:bar)).to be(bar) } end context 'equalization behavior' do specify 'composed objects are equalized on attributes' do expect(instance_a).to eql(instance_b) expect(instance_a.hash).to eql(instance_b.hash) expect(instance_a).to eql(instance_b) expect(instance_a).to_not be(instance_c) expect(instance_a).to_not eql(instance_c) end end context 'when composing too many objects' do specify 'it raises an error' do expect { Concord.new(:a, :b, :c, :d) }.to raise_error(RuntimeError, 'Composition of more than 3 objects is not allowed') expect { Concord.new(:a, :b, :c) }.to_not raise_error end end context Concord::Public do let(:class_under_test) do Class.new do include Concord::Public.new(:foo, :bar) end end it 'should create public attr readers' do object = class_under_test.new(:foo, :bar) expect(object.foo).to eql(:foo) expect(object.bar).to eql(:bar) end end end concord-0.1.5/spec/spec_helper.rb0000644000175200017520000000007713631621556016162 0ustar debiandebianrequire 'devtools' require 'concord' Devtools.init_spec_helper concord-0.1.5/lib/0000755000175200017520000000000013631621556013154 5ustar debiandebianconcord-0.1.5/lib/concord.rb0000644000175200017520000000462013631621556015132 0ustar debiandebianrequire 'adamantium' require 'equalizer' # A mixin to define a composition class Concord < Module include Adamantium::Flat, Equalizer.new(:names) # The maximum number of objects the hosting class is composed of MAX_NR_OF_OBJECTS = 3 # Return names # # @return [Enumerable] # # @api private # attr_reader :names private # Initialize object # # @return [undefined] # # @api private # def initialize(*names) if names.length > MAX_NR_OF_OBJECTS raise "Composition of more than #{MAX_NR_OF_OBJECTS} objects is not allowed" end @names = names @module = Module.new define_initialize define_readers define_equalizer end # Hook run when module is included # # @param [Class|Module] descendant # # @return [undefined] # # @api private # def included(descendant) descendant.send(:include, @module) end # Define equalizer # # @param [Class|Module] descendant # # @return [undefined] # # @api private # def define_equalizer @module.send(:include, Equalizer.new(*@names)) end # Define readers # # @param [Class|Module] descendant # # @return [undefined] # # @api private # def define_readers attribute_names = names @module.class_eval do attr_reader(*attribute_names) protected(*attribute_names) end end # Define initialize method # # @param [Class|Module] descendant # # @return [undefined] # # @api private # def define_initialize ivars, size = instance_variable_names, names.size @module.class_eval do define_method :initialize do |*args| args_size = args.size if args_size != size raise ArgumentError, "wrong number of arguments (#{args_size} for #{size})" end ivars.zip(args) { |ivar, arg| instance_variable_set(ivar, arg) } end private :initialize end end # Return instance variable names # # @return [String] # # @api private # def instance_variable_names names.map { |name| "@#{name}" } end # Mixin for public attribute readers class Public < self # Hook called when module is included # # @param [Class,Module] descendant # # @return [undefined] # # @api private # def included(descendant) super @names.each do |name| descendant.send(:public, name) end end end # Public end # Concord concord-0.1.5/config/0000755000175200017520000000000013631621556013653 5ustar debiandebianconcord-0.1.5/config/yardstick.yml0000644000175200017520000000002313631621556016366 0ustar debiandebian--- threshold: 100 concord-0.1.5/config/rubocop.yml0000644000175200017520000000320213631621556016044 0ustar debiandebianinherit_from: ../.rubocop.yml AllCops: Includes: - '**/*.rake' - 'Gemfile' - 'Gemfile.triage' # Avoid parameter lists longer than five parameters. ParameterLists: Max: 3 CountKeywordArgs: true MethodLength: CountComments: false Max: 15 # Avoid more than `Max` levels of nesting. BlockNesting: Max: 3 # Align with the style guide. CollectionMethods: PreferredMethods: collect: 'map' inject: 'reduce' find: 'detect' find_all: 'select' # Limit line length LineLength: Max: 113 # TODO: lower to 79 once the rubocop branch in shared/Gemfile is removed ClassLength: Max: 204 # Disabled because of indenting with private keyword in class bodies. IndentationWidth: Enabled: false # I like raise more SignalException: Enabled: false # False positive in unparser source OneLineConditional: Enabled: false Documentation: Enabled: false # Disable documentation checking until a class needs to be documented once Documentation: Enabled: false # Do not favor modifier if/unless usage when you have a single-line body IfUnlessModifier: Enabled: false # Allow case equality operator (in limited use within the specs) CaseEquality: Enabled: false # Constants do not always have to use SCREAMING_SNAKE_CASE ConstantName: Enabled: false # Not all trivial readers/writers can be defined with attr_* methods TrivialAccessors: Enabled: false # Do not prefer do/end over {} for multiline blocks Blocks: Enabled: false # I like to have an empty line before closing the currently opened body EmptyLinesAroundBody: Enabled: false # I like my style more AccessModifierIndentation: Enabled: false concord-0.1.5/config/roodi.yml0000644000175200017520000000145613631621556015520 0ustar debiandebian--- AbcMetricMethodCheck: score: 25.1 AssignmentInConditionalCheck: { } CaseMissingElseCheck: { } ClassLineCountCheck: { line_count: 317 } ClassNameCheck: pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ ClassVariableCheck: { } CyclomaticComplexityBlockCheck: { complexity: 3 } CyclomaticComplexityMethodCheck: { complexity: 4 } EmptyRescueBodyCheck: { } ForLoopCheck: { } MethodLineCountCheck: { line_count: 14 } MethodNameCheck: pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/ ModuleLineCountCheck: { line_count: 320 } ModuleNameCheck: pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ ParameterNumberCheck: { parameter_count: 3 } concord-0.1.5/config/reek.yml0000644000175200017520000000314113631621556015323 0ustar debiandebianUncommunicativeParameterName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ TooManyMethods: max_methods: 14 enabled: true exclude: [] max_instance_variables: 4 UncommunicativeMethodName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^[a-z]$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ LongParameterList: max_params: 2 exclude: [] enabled: true overrides: {} FeatureEnvy: exclude: - Concord#define_readers enabled: true ClassVariable: exclude: [] enabled: true BooleanParameter: exclude: [] enabled: true IrresponsibleModule: exclude: [] enabled: true UncommunicativeModuleName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ NestedIterators: ignore_iterators: [] exclude: - Concord#define_initialize enabled: true max_allowed_nesting: 1 TooManyStatements: max_statements: 7 exclude: - Concord#define_initialize enabled: true DuplicateMethodCall: allow_calls: [] exclude: [] enabled: true max_calls: 1 UtilityFunction: max_helper_calls: 0 exclude: [] enabled: true Attribute: exclude: [] enabled: false UncommunicativeVariableName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ RepeatedConditional: enabled: true max_ifs: 1 DataClump: exclude: [] enabled: true max_copies: 0 min_clump_size: 2 ControlParameter: exclude: [] enabled: true LongYieldList: max_params: 0 exclude: [] enabled: true concord-0.1.5/config/mutant.yml0000644000175200017520000000007013631621556015703 0ustar debiandebianname: concord namespace: Concord strategy: --rspec-unit concord-0.1.5/config/flog.yml0000644000175200017520000000002413631621556015321 0ustar debiandebian--- threshold: 25.5 concord-0.1.5/config/flay.yml0000644000175200017520000000004313631621556015326 0ustar debiandebian--- threshold: 3 total_score: 18.0 concord-0.1.5/concord.gemspec0000644000175200017520000000120213631621556015375 0ustar debiandebian# -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = 'concord' s.version = '0.1.5' s.authors = ['Markus Schirp'] s.email = ['mbj@schirp-dso.com'] s.homepage = 'https://github.com/mbj/concord' s.summary = %q{Helper for object composition} s.license = 'MIT' s.description = s.summary s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {spec}/*`.split("\n") s.executables = [] s.require_paths = ['lib'] s.required_ruby_version = '>= 1.9.3' s.add_dependency('adamantium', '~> 0.2.0') s.add_dependency('equalizer', '~> 0.0.9') end concord-0.1.5/circle.yml0000644000175200017520000000006013631621556014366 0ustar debiandebian--- test: override: - bundle exec rake ci concord-0.1.5/Rakefile0000644000175200017520000000040713631621556014054 0ustar debiandebianrequire 'devtools' Devtools.init_rake_tasks Rake.application.load_imports task('metrics:mutant').clear namespace :metrics do task :mutant => :coverage do $stderr.puts 'Concord is a dependency of mutant and zombification is currently defunkt :(' end end concord-0.1.5/README.md0000644000175200017520000000312313631621556013664 0ustar debiandebianconcord ======= [![Build Status](https://secure.travis-ci.org/mbj/concord.png?branch=master)](http://travis-ci.org/mbj/concord) [![Dependency Status](https://gemnasium.com/mbj/concord.png)](https://gemnasium.com/mbj/concord) [![Code Climate](https://codeclimate.com/github/mbj/concord.png)](https://codeclimate.com/github/mbj/concord) Library to transform this: ```ruby class ComposedObject include Equalizer.new(:foo, :bar) # Return foo # # @return [Foo] # # @api private # attr_reader :foo protected :foo # Return bar # # @return [Bar] # # @api private # attr_reader :bar protected :bar # Initialize object # # @param [Foo] foo # @param [Bar] bar # # @return [undefined] # # @api private # def initialize(foo, bar) @foo, @bar = foo, bar end end ``` Into shorter and easier to parse by eyes: ```ruby class ComposedObject include Concord.new(:foo, :bar) end ``` Sure the replacement is missing YARD docs, but IMHO it is better. Rubies ------ Tested under all >= 1.9 rubies. Installation ------------ Install the gem `concord` via your prefered method. Credits ------- * [mbj](https://github.com/mbj) Contributing ------------- * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a future version unintentionally. * Commit, do not mess with Rakefile or version (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) * Send me a pull request. Bonus points for topic branches. License ------- See LICENSE concord-0.1.5/LICENSE0000644000175200017520000000204113631621556013410 0ustar debiandebianCopyright (c) 2012 Markus Schirp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. concord-0.1.5/Guardfile0000644000175200017520000000035613631621556014237 0ustar debiandebian# A sample Guardfile # More info at https://github.com/guard/guard#readme guard 'rspec' do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } end concord-0.1.5/Gemfile.devtools0000644000175200017520000000315413631621556015542 0ustar debiandebian# encoding: utf-8 group :development do gem 'rake', '~> 10.2.1' gem 'rspec', '~> 2.14.1' gem 'rspec-core', '~> 2.14.8' gem 'yard', '~> 0.8.7.4' platform :rbx do gem 'rubysl-singleton', '~> 2.0.0' end end group :yard do gem 'kramdown', '~> 1.3.3' end group :guard do gem 'guard', '~> 2.6.0' gem 'guard-bundler', '~> 2.0.0' gem 'guard-rspec', '~> 4.2.8' gem 'guard-rubocop', '~> 1.0.2' # file system change event handling gem 'listen', '~> 2.7.1' gem 'rb-fchange', '~> 0.0.6', require: false gem 'rb-fsevent', '~> 0.9.4', require: false gem 'rb-inotify', '~> 0.9.3', require: false # notification handling gem 'libnotify', '~> 0.8.2', require: false gem 'rb-notifu', '~> 0.0.4', require: false gem 'terminal-notifier-guard', '~> 1.5.3', require: false end group :metrics do gem 'coveralls', '~> 0.7.0' gem 'flay', '~> 2.4.0' gem 'flog', '~> 4.2.0' gem 'reek', '~> 1.3.7' gem 'rubocop', '~> 0.19.1' gem 'simplecov', '~> 0.8.2' gem 'yardstick', '~> 0.9.9' platforms :mri do gem 'mutant', '~> 0.5.10' gem 'mutant-rspec', '~> 0.5.10' end platforms :ruby_19, :ruby_20 do gem 'yard-spellcheck', '~> 0.1.5' end platform :rbx do gem 'json', '~> 1.8.1' gem 'racc', '~> 1.4.11' gem 'rubysl-logger', '~> 2.0.0' gem 'rubysl-open-uri', '~> 2.0.0' gem 'rubysl-prettyprint', '~> 2.0.3' end end group :benchmarks do gem 'rbench', '~> 0.2.3' end platform :jruby do group :jruby do gem 'jruby-openssl', '~> 0.8.5' end end concord-0.1.5/Gemfile0000644000175200017520000000023013631621556013674 0ustar debiandebiansource 'https://rubygems.org' gemspec gem 'devtools', git: 'https://github.com/rom-rb/devtools.git', branch: 'master' eval_gemfile 'Gemfile.devtools' concord-0.1.5/Changelog.md0000644000175200017520000000107213631621556014617 0ustar debiandebian# v0.1.5 2014-04-10 * Dependency bumps * Support calling (z)super from custom initialize # v0.1.4 2013-09-22 * Dependency bumps # v0.1.3 2013-08-31 * Dependency bumps # v0.1.2 2013-08-07 * Dependency bumps * Internal refactorings # v0.1.1 2013-05-15 + Add Concord::Public mixin defaulting to public attr_readers # v0.1.0 2013-05-15 * [change] Set default attribute visibility to protected # v0.0.3 2013-03-08 * [fix] 1.9.2 visibility problem # v0.0.2 2013-03-07 * [change] remove unneded backports dependency # v0.0.1 2013-03-06 * First public release! concord-0.1.5/.travis.yml0000644000175200017520000000041613631621556014520 0ustar debiandebianlanguage: ruby script: 'bundle exec rake ci' rvm: - 1.9.3 - 2.0.0 - jruby-19mode - jruby-head - rbx matrix: allow_failures: - rvm: ruby-head notifications: irc: channels: - irc.freenode.org#rom-rb on_success: never on_failure: change concord-0.1.5/.rubocop.yml0000644000175200017520000000016213631621556014657 0ustar debiandebianAllCops: Includes: - 'Gemfile' Excludes: - 'Gemfile.devtools' - 'vendor/**' - 'benchmarks/**' concord-0.1.5/.rspec0000644000175200017520000000011213631621556013515 0ustar debiandebian--color --format progress --profile --order random --fail-fast --warnings concord-0.1.5/.gitignore0000644000175200017520000000004413631621556014374 0ustar debiandebian/tmp /Gemfile.lock /.bundle /vendor concord-0.1.5/.circle.yml0000644000175200017520000000006013631621556014444 0ustar debiandebian--- test: override: - bundle exec rake ci