super_module 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
+ SHA1:
3
+ metadata.gz: def423de958bb4f6b3d2c6b3edb60908d42bbe86
4
+ data.tar.gz: 962866a97336aaeeebd16386e1cf37417e1d2aa9
5
+ SHA512:
6
+ metadata.gz: 99668ddec0c2e332493f7cda830428e4915d65eaf35bde9b5a0336233396425c458746734082917028a310b8fa0e4a01d0b430f0f3a78a31b7cd5afdd541e5c1
7
+ data.tar.gz: fb848a9f6979fe0f079ddc9d3967eb600b85186659ce6457d220ec5ce55be0c460928fe09e5403cfe0689009a4c93ae9a3ce4102e1b07ac27785027f525e7b02
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Andy Maleh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # SuperModule
2
+ [![Gem Version](https://badge.fury.io/rb/super_module.png)](http://badge.fury.io/rb/super_module)
3
+ [![Build Status](https://api.travis-ci.org/AndyObtiva/super_module.png?branch=master)](https://travis-ci.org/AndyObtiva/super_module)
4
+ [![Coverage Status](https://coveralls.io/repos/AndyObtiva/super_module/badge.png?branch=master)](https://coveralls.io/r/AndyObtiva/super_module?branch=master)
5
+ [![Code Climate](https://codeclimate.com/github/AndyObtiva/super_module.png)](https://codeclimate.com/github/AndyObtiva/super_module)
6
+
7
+ Tired of Ruby's modules not allowing you to mix in class methods easily?
8
+ Tired of writing complex code and using complex libraries like ActiveSupport::Concern to accomplish that goal?
9
+
10
+ Well, worry no more! SuperModule comes to the rescue!
11
+
12
+ ![SuperModule](https://raw.githubusercontent.com/AndyObtiva/super_module/master/SuperModule.jpg)
13
+
14
+ SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base).
15
+
16
+ This succeeds ActiveSupport::Concern by offering lighter syntax and simpler module dependency support.
17
+
18
+ ## Instructions
19
+
20
+ ### 1) Install and require gem
21
+
22
+ <b>Using Bundler</b>
23
+
24
+ Add the following to Gemfile: <pre>gem 'super_module', '1.0.0'</pre>
25
+ Run: <code>bundle</code>
26
+
27
+ It will automatically get required in the application when loading with bundler (e.g. in a Rails application)
28
+
29
+ <b>Using RubyGem Directly</b>
30
+
31
+ Run: <pre>gem install super_module</pre>
32
+ (add <code>--no-ri --no-rdoc</code> if you wish to skip downloading them for a faster install)
33
+
34
+ Add <code>require 'super_module'</code> at the top of your Ruby file
35
+
36
+ ### 2) Include SuperModule at the top of the module
37
+
38
+ > module UserIdentifiable
39
+ > include SuperModule
40
+ >
41
+ > belongs_to :user
42
+ > validates :user_id, presence: true
43
+ >
44
+ > def self.most_active_user
45
+ > User.find_by_id(select('count(id) as head_count, user_id').group('user_id').order('count(id) desc').first.user_id)
46
+ > end
47
+ >
48
+ > def slug
49
+ > "#{self.class.name}_#{user_id}"
50
+ > end
51
+ > end
52
+
53
+ ### 3) Mix newly defined module into a class or another super module
54
+
55
+ > class ClubParticipation < ActiveRecord::Base
56
+ > include UserIdentifiable
57
+ > end
58
+ > class CourseEnrollment < ActiveRecord::Base
59
+ > include UserIdentifiable
60
+ > end
61
+ > module Accountable
62
+ > include SuperModule
63
+ > include UserIdentifiable
64
+ > end
65
+ > class Activity < ActiveRecord::Base
66
+ > include Accountable
67
+ > end
68
+
69
+ ### 4) Start using by invoking class methods or instance methods
70
+
71
+ > CourseEnrollment.most_active_user
72
+ > ClubParticipation.most_active_user
73
+ > Activity.last.slug
74
+ > ClubParticipation.create(club_id: club.id, user_id: user.id).slug
75
+ > CourseEnrollment.new(course_id: course.id).valid?
76
+
77
+ ## Example
78
+
79
+ > require 'super_module'
80
+ >
81
+ > module Foo
82
+ > include SuperModule
83
+ >
84
+ > validates :credit_card_id, presence: true
85
+ >
86
+ > def foo
87
+ > puts 'foo'
88
+ > 'foo'
89
+ > end
90
+ >
91
+ > def self.foo
92
+ > puts 'self.foo'
93
+ > 'self.foo'
94
+ > end
95
+ > end
96
+ >
97
+ > module Bar
98
+ > include SuperModule
99
+ > include Foo
100
+ >
101
+ > validates :user_id, presence: true
102
+ >
103
+ > def bar
104
+ > puts 'bar'
105
+ > 'bar'
106
+ > end
107
+ >
108
+ > def self.bar
109
+ > puts 'self.bar'
110
+ > 'self.bar'
111
+ > end
112
+ > end
113
+ >
114
+ > class MediaAuthorization < ActiveRecord::Base
115
+ > include Bar
116
+ > end
117
+ >
118
+ > MediaAuthorization.create.errors.messages.inspect
119
+
120
+ => "{:credit_card_id=>[\"can't be blank\"], :user_id=>[\"can't be blank\"]}"
121
+
122
+ > MediaAuthorization.new.foo
123
+
124
+ => "foo"
125
+
126
+ > MediaAuthorization.new.bar
127
+
128
+ => "bar"
129
+
130
+ > MediaAuthorization.foo
131
+
132
+ => "self.foo"
133
+
134
+ > MediaAuthorization.bar
135
+
136
+ => "self.bar"
137
+
138
+ ## Design Limitations
139
+
140
+ This has been designed to be used only in the code definition of a module.
141
+
142
+ ## Copyright
143
+
144
+ Copyright (c) 2014 Andy Maleh. See LICENSE.txt for
145
+ further details.
146
+
data/SuperModule.jpg ADDED
Binary file
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,66 @@
1
+ # SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base).
2
+ #
3
+ # Author:: Andy Maleh
4
+ # Copyright:: Copyright (c) 2014 Andy Maleh
5
+ # License:: MIT License
6
+
7
+ # This module allows defining class methods and method invocations the same way a super class does without using def included(base).
8
+
9
+ module SuperModule
10
+ EXCLUDED_SINGLETON_METHODS = [
11
+ :__super_module_class_methods,
12
+ :__invoke_super_module_class_method_calls,
13
+ :__define_super_module_class_methods,
14
+ :__restore_original_method_missing,
15
+ :included, :method_missing,
16
+ :singleton_method_added
17
+ ]
18
+ def self.included(base)
19
+ base.class_eval do
20
+ class << self
21
+
22
+ def include(base, &block)
23
+ method_missing('include', base, &block)
24
+ end
25
+
26
+ def __super_module_class_method_calls
27
+ @__super_module_class_method_calls ||= []
28
+ end
29
+
30
+ def __super_module_class_methods
31
+ @__super_module_class_methods ||= []
32
+ end
33
+
34
+ def singleton_method_added(method_name)
35
+ __super_module_class_methods << [method_name, method(method_name)] unless EXCLUDED_SINGLETON_METHODS.include?(method_name)
36
+ super
37
+ end
38
+
39
+ def method_missing(method_name, *args, &block)
40
+ __super_module_class_method_calls << [method_name, args, block]
41
+ end
42
+
43
+ def __invoke_super_module_class_method_calls(base)
44
+ __super_module_class_method_calls.each do |method_name, args, block|
45
+ base.class_eval do
46
+ send(method_name, *args, &block)
47
+ end
48
+ end
49
+ end
50
+
51
+ def __define_super_module_class_methods(base)
52
+ __super_module_class_methods.each do |method_name, method|
53
+ base.class_eval do
54
+ self.class.send(:define_method, method_name, &method)
55
+ end
56
+ end
57
+ end
58
+
59
+ def included(base)
60
+ __invoke_super_module_class_method_calls(base)
61
+ __define_super_module_class_methods(base)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe SuperModule do
4
+ module Foo
5
+ include SuperModule
6
+ validates 'foo', presence: true
7
+
8
+ def self.foo
9
+ 'self.foo'
10
+ end
11
+
12
+ def foo
13
+ 'foo'
14
+ end
15
+ end
16
+ module Bar
17
+ include SuperModule
18
+ validates 'bar', presence: true
19
+
20
+ class << self
21
+ def bar
22
+ 'self.bar'
23
+ end
24
+ end
25
+
26
+ def bar
27
+ 'bar'
28
+ end
29
+ end
30
+ class FakeActiveRecord
31
+ class << self
32
+ def validates(attribute, options)
33
+ validations << [attribute, options]
34
+ end
35
+ def validations
36
+ @validations ||= []
37
+ end
38
+ end
39
+ end
40
+
41
+ context "a base class includes a module enhanced as a super module" do
42
+ before do
43
+ FakeActiveRecord.send(:include, Foo)
44
+ end
45
+
46
+ it 'allows invoking class methods in the including base class body' do
47
+ FakeActiveRecord.validations.should include(['foo', {presence: true}])
48
+ end
49
+ it 'includes instance methods in the including base class' do
50
+ instance = FakeActiveRecord.new
51
+
52
+ instance.foo.should == 'foo'
53
+ end
54
+ it 'includes class methods in the including base class' do
55
+ FakeActiveRecord.foo.should == 'self.foo'
56
+ end
57
+ end
58
+
59
+ context "a base class includes a base module enhanced as a super module that includes another module enhanced as a super module" do
60
+ before do
61
+ Bar.send(:include, Foo)
62
+ FakeActiveRecord.send(:include, Bar)
63
+ end
64
+
65
+ it 'allows invoking class methods in the including base class body' do
66
+ FakeActiveRecord.validations.should include(['foo', {presence: true}])
67
+ FakeActiveRecord.validations.should include(['bar', {presence: true}])
68
+ end
69
+ it 'includes instance methods in the including base class' do
70
+ instance = FakeActiveRecord.new
71
+
72
+ instance.foo.should == 'foo'
73
+ instance.bar.should == 'bar'
74
+ end
75
+ it 'includes class methods in the including base class' do
76
+ FakeActiveRecord.foo.should == 'self.foo'
77
+ FakeActiveRecord.bar.should == 'self.bar'
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: super_module 1.0.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "super_module"
9
+ s.version = "1.0.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Andy Maleh"]
14
+ s.date = "2014-03-27"
15
+ s.description = "SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base). This also succeeds ActiveSupport::Concern by offering lighter syntax"
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "SuperModule.jpg",
25
+ "VERSION",
26
+ "lib/super_module.rb",
27
+ "spec/lib/super_module_spec.rb",
28
+ "super_module.gemspec"
29
+ ]
30
+ s.homepage = "http://github.com/AndyObtiva/super_module"
31
+ s.licenses = ["MIT"]
32
+ s.rubygems_version = "2.2.2"
33
+ s.summary = "SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base). This also succeeds ActiveSupport::Concern by offering lighter syntax"
34
+
35
+ if s.respond_to? :specification_version then
36
+ s.specification_version = 4
37
+
38
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
40
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
41
+ else
42
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
43
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
44
+ end
45
+ else
46
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
47
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
48
+ end
49
+ end
50
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: super_module
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andy Maleh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jeweler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ description: SuperModule allows defining class methods and method invocations the
42
+ same way a super class does without using def included(base). This also succeeds
43
+ ActiveSupport::Concern by offering lighter syntax
44
+ email:
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files:
48
+ - LICENSE.txt
49
+ - README.md
50
+ files:
51
+ - ".document"
52
+ - LICENSE.txt
53
+ - README.md
54
+ - SuperModule.jpg
55
+ - VERSION
56
+ - lib/super_module.rb
57
+ - spec/lib/super_module_spec.rb
58
+ - super_module.gemspec
59
+ homepage: http://github.com/AndyObtiva/super_module
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.2.2
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: SuperModule allows defining class methods and method invocations the same
83
+ way a super class does without using def included(base). This also succeeds ActiveSupport::Concern
84
+ by offering lighter syntax
85
+ test_files: []