activerecord-concernable 0.4.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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/activerecord-concernable.gemspec +26 -0
- data/lib/activerecord-concernable.rb +67 -0
- data/lib/activerecord-concernable/version.rb +5 -0
- metadata +93 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Blake Taylor
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Activerecord::Concernable
|
|
2
|
+
|
|
3
|
+
A DSL for defining ActiveRecord concerns.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'activerecord-concernable'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install activerecord-concernable
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
The Concernable DSL is available within any ActiveRecord::Base. The DSL consist
|
|
22
|
+
of a single command `concern`. Use it to define concerns for the object. The
|
|
23
|
+
body of the concern follows the same rules that of [ActiveSupport::Concern][1].
|
|
24
|
+
|
|
25
|
+
Defining concerns:
|
|
26
|
+
|
|
27
|
+
class Notification < ActiveRecord::Base
|
|
28
|
+
|
|
29
|
+
belongs_to :user
|
|
30
|
+
belongs_to :notifiable, polymorphic: true
|
|
31
|
+
|
|
32
|
+
# Extend user with has_many :notifications. When concern is passed a class
|
|
33
|
+
# the generated concern will automatically be mixed into that class.
|
|
34
|
+
concern User do
|
|
35
|
+
included do
|
|
36
|
+
has_many :notifications
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Create a named concern by passing a symbol. Mix into any number of
|
|
41
|
+
# classes by passing them as `:of` in the options hash.
|
|
42
|
+
concern :notifiable, of: [Comments, Posts] do
|
|
43
|
+
included do
|
|
44
|
+
has_many :notifications, as: :subject, dependent: :destroy
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_notification(message)
|
|
48
|
+
notifications.create(message: message)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
### Why would I want to do this?
|
|
54
|
+
|
|
55
|
+
The primary reason for using the DSL is to keep ActiveRecord models skinny and
|
|
56
|
+
well defined, and to avoid the inevitability of monolithic model object (1000
|
|
57
|
+
line user.rb anyone?).
|
|
58
|
+
|
|
59
|
+
The idea is that as new models are introduced, they will often be related, and
|
|
60
|
+
therefore "concerned" with other models in the system. To a large extent, this
|
|
61
|
+
is the very point of relational data and ActiveRecord. Unfortunately, This
|
|
62
|
+
creates pain points at the cruxes of the domain model. New objects are concerned
|
|
63
|
+
with the popular objects, and the popular objects accumulate the inverse
|
|
64
|
+
concerns and functionality.
|
|
65
|
+
|
|
66
|
+
Concern modules can solve this problem is by allowing you to avoid adding
|
|
67
|
+
additional code to the centralized definition of the core class when adding a
|
|
68
|
+
new associated class. Instead, you simply add a concern and mix it in.
|
|
69
|
+
|
|
70
|
+
This is essentially what the DSL does, but takes things a few steps further, by
|
|
71
|
+
allowing you to easily nest the concern definition right inside the dependent
|
|
72
|
+
model and then mix into the dependant classes unobtrusively.
|
|
73
|
+
|
|
74
|
+
## Contributing
|
|
75
|
+
|
|
76
|
+
1. Fork it
|
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
78
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
80
|
+
5. Create new Pull Request
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
[1]: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'activerecord-concernable/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "activerecord-concernable"
|
|
8
|
+
gem.version = Activerecord::Concernable::VERSION
|
|
9
|
+
gem.authors = ["Blake Taylor"]
|
|
10
|
+
gem.email = ["blakefrost@gmail.com"]
|
|
11
|
+
gem.description = %q{A DSL for defining ActiveRecord concerns}
|
|
12
|
+
gem.summary = %q{
|
|
13
|
+
Helps keep models skinny and code understandable by making it simple to
|
|
14
|
+
define concerns and mix them into the affect class right from within the
|
|
15
|
+
concerned class. See readme for more information.
|
|
16
|
+
}
|
|
17
|
+
gem.homepage = ""
|
|
18
|
+
|
|
19
|
+
gem.files = `git ls-files`.split($/)
|
|
20
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
22
|
+
gem.require_paths = ["lib"]
|
|
23
|
+
|
|
24
|
+
gem.add_dependency('activerecord')
|
|
25
|
+
gem.add_development_dependency('rake')
|
|
26
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require "activerecord-concernable/version"
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Concernable
|
|
5
|
+
# Defines a concern.
|
|
6
|
+
#
|
|
7
|
+
# Concern will be named by convention below the ::Concerns module. Concern
|
|
8
|
+
# will be wrapped in namespace named by convention from the class defining the
|
|
9
|
+
# concern. For example, a User concern within the Notification class would
|
|
10
|
+
# be available at ::Concerns::Notification::User
|
|
11
|
+
#
|
|
12
|
+
# By convention, if a class is passed as the concern name, the concern will be
|
|
13
|
+
# automatically mixed into the passed class. If this functionality is not
|
|
14
|
+
# desirable, pass the name as a symbol i.e. :user.
|
|
15
|
+
#
|
|
16
|
+
# To mix into additional classes, pass them classes as an array to the of
|
|
17
|
+
# option key.
|
|
18
|
+
#
|
|
19
|
+
# Example:
|
|
20
|
+
#
|
|
21
|
+
# class Notification
|
|
22
|
+
# extend Concernable
|
|
23
|
+
#
|
|
24
|
+
# concern :user do
|
|
25
|
+
# included do
|
|
26
|
+
# has_many :notifications
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# concern :notifiable, of: [Comments, Posts] do
|
|
31
|
+
# include do
|
|
32
|
+
# has_many :notifications, as: :subject, dependent: :destroy
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# def create_notifcation(*args)
|
|
36
|
+
# notications.create(*args)
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
def concern(name, opts={}, &block)
|
|
42
|
+
namespace = self.to_s.split('::').reduce(::Concerns) do |namespace, module_name|
|
|
43
|
+
namespace.const_defined?(module_name, false) ? namespace.const_get(module_name) : namespace.const_set(module_name, Module.new)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Create and populate concern module.
|
|
47
|
+
camelized_name = name.to_s.camelize
|
|
48
|
+
concern = Module.new
|
|
49
|
+
concern.send(:extend, ActiveSupport::Concern)
|
|
50
|
+
concern.class_eval(&block)
|
|
51
|
+
concern = namespace.const_set(camelized_name, concern)
|
|
52
|
+
|
|
53
|
+
# Mix-in concern
|
|
54
|
+
opts.symbolize_keys!
|
|
55
|
+
opts[:of] = Array(opts[:of])
|
|
56
|
+
opts[:of] << name if name.instance_of? Class
|
|
57
|
+
Array(opts[:of]).each { |klass| klass.send(:include, concern) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Defines namespace for where concerns will be defined to.
|
|
64
|
+
module Concerns; end
|
|
65
|
+
|
|
66
|
+
# Extend Active Record Base with Concernable.
|
|
67
|
+
ActiveRecord::Base.extend ActiveRecord::Concernable
|
metadata
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: activerecord-concernable
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.4.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Blake Taylor
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-02-02 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: activerecord
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: rake
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
description: A DSL for defining ActiveRecord concerns
|
|
47
|
+
email:
|
|
48
|
+
- blakefrost@gmail.com
|
|
49
|
+
executables: []
|
|
50
|
+
extensions: []
|
|
51
|
+
extra_rdoc_files: []
|
|
52
|
+
files:
|
|
53
|
+
- .gitignore
|
|
54
|
+
- Gemfile
|
|
55
|
+
- LICENSE.txt
|
|
56
|
+
- README.md
|
|
57
|
+
- Rakefile
|
|
58
|
+
- activerecord-concernable.gemspec
|
|
59
|
+
- lib/activerecord-concernable.rb
|
|
60
|
+
- lib/activerecord-concernable/version.rb
|
|
61
|
+
homepage: ''
|
|
62
|
+
licenses: []
|
|
63
|
+
post_install_message:
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
none: false
|
|
69
|
+
requirements:
|
|
70
|
+
- - ! '>='
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
segments:
|
|
74
|
+
- 0
|
|
75
|
+
hash: 1236418441682571541
|
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
|
+
none: false
|
|
78
|
+
requirements:
|
|
79
|
+
- - ! '>='
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
segments:
|
|
83
|
+
- 0
|
|
84
|
+
hash: 1236418441682571541
|
|
85
|
+
requirements: []
|
|
86
|
+
rubyforge_project:
|
|
87
|
+
rubygems_version: 1.8.23
|
|
88
|
+
signing_key:
|
|
89
|
+
specification_version: 3
|
|
90
|
+
summary: Helps keep models skinny and code understandable by making it simple to define
|
|
91
|
+
concerns and mix them into the affect class right from within the concerned class.
|
|
92
|
+
See readme for more information.
|
|
93
|
+
test_files: []
|