extended_attributes 1.0.1
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 +2 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +22 -0
- data/README.md +90 -0
- data/Rakefile +13 -0
- data/extended_attributes-1.0.0.gem +0 -0
- data/extended_attributes.gemspec +20 -0
- data/lib/extended_attributes.rb +37 -0
- data/spec/date_methods.rb +8 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/user.rb +28 -0
- data/spec/user_spec.rb +28 -0
- metadata +91 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
== extended_attributes
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2011 Chirantan Rajhans.
|
|
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,90 @@
|
|
|
1
|
+
# Extended Attributes
|
|
2
|
+
_Add custom behavior to your model attributes in ActiveRecord_
|
|
3
|
+
|
|
4
|
+
How often do you have to have an instance method implemented in a model but only to work with just 1 attribute?
|
|
5
|
+
|
|
6
|
+
```ruby
|
|
7
|
+
class User < ActiveRecord::Base
|
|
8
|
+
|
|
9
|
+
def first_name
|
|
10
|
+
name.split(' ').first
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
But attributes are also objects at the end of the day right? Should the first_name method belong to the attribute name? With this gem you can extend your attribute by mixing modules with them or having attribute specific methods defined on them. Just like our relationship objects.
|
|
17
|
+
|
|
18
|
+
In your Gemfile
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
gem 'extended_attributes'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
$ bundle install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
and now you can do:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
class User < ActiveRecord::Base
|
|
33
|
+
|
|
34
|
+
extend_attribute :name do
|
|
35
|
+
|
|
36
|
+
def first
|
|
37
|
+
split(' ').first
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def last
|
|
41
|
+
split(' ').last
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
And you will be able to do:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
user = User.find(:first)
|
|
53
|
+
user.name # John Anderson
|
|
54
|
+
user.name.first # John
|
|
55
|
+
user.name.last # Anderson
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Additionally, you can also have modules exteded on the attributes
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
module NameMethods
|
|
62
|
+
|
|
63
|
+
def first
|
|
64
|
+
split(' ').first
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def last
|
|
68
|
+
split(' ').last
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class User < ActiveRecord::Base
|
|
74
|
+
|
|
75
|
+
extend_attribute :name, :extend => NameMethods
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Why?
|
|
81
|
+
|
|
82
|
+
Extending attributes adds modularity to your design, better object orientation and makes interfaces clean.
|
|
83
|
+
|
|
84
|
+
### Dealing with Fixnum
|
|
85
|
+
|
|
86
|
+
[Fixnums cannot have singleton methods](www.ruby-forum.com/topic/50170). Thus, if you try to extend an attribute that is a Fixnum, the whole behavior will be `include`d on Fixnum class, which means that the same behavior will be available on all instances of Fixnum throughout your application. So be careful with them.
|
|
87
|
+
|
|
88
|
+
### Note
|
|
89
|
+
|
|
90
|
+
This gem was developed because I liked it and it serves my purpose. Feel free to add to it. I’ll be happy to accept pull requests.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler'
|
|
3
|
+
Bundler.setup :default, :development
|
|
4
|
+
|
|
5
|
+
desc 'Default: run specs'
|
|
6
|
+
task :default => :spec
|
|
7
|
+
|
|
8
|
+
require 'rspec/core/rake_task'
|
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
|
10
|
+
t.pattern = "spec/**/*_spec.rb"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Bundler::GemHelper.install_tasks
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
$:.push File.dirname(__FILE__) + '/lib'
|
|
2
|
+
require 'extended_attributes.rb'
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.name = %q{extended_attributes}
|
|
6
|
+
gem.authors = ["Chirantan Rajhans"]
|
|
7
|
+
gem.date = %q{2011-10-10}
|
|
8
|
+
gem.description = %q{Extend behavior of attributes of your active record models.}
|
|
9
|
+
gem.summary = "Objectify your active record attributes."
|
|
10
|
+
gem.email = %q{chirantan.rajhans@gmail.com}
|
|
11
|
+
gem.homepage = 'http://github.com/chirantan'
|
|
12
|
+
|
|
13
|
+
gem.add_runtime_dependency 'active_record', '< 3.1.0'
|
|
14
|
+
|
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
16
|
+
gem.files = `git ls-files`.split("\n")
|
|
17
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
gem.require_paths = ['lib']
|
|
19
|
+
gem.version = '1.0.1'
|
|
20
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_record'
|
|
3
|
+
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
class Base
|
|
6
|
+
class << self
|
|
7
|
+
def extend_attribute(attr, options = {}, &block)
|
|
8
|
+
after_initialize ExtendAttribute.new(attr, options, block)
|
|
9
|
+
after_find ExtendAttribute.new(attr, options, block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ExtendAttribute
|
|
14
|
+
|
|
15
|
+
def initialize(attr, options = {}, block = nil)
|
|
16
|
+
@attr = attr
|
|
17
|
+
@options = options
|
|
18
|
+
@block = block
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def after_initialize(record)
|
|
22
|
+
modules = [*@options[:extend]].compact
|
|
23
|
+
modules << Module.new(&@block) if @block
|
|
24
|
+
modules.each do |mod|
|
|
25
|
+
attribute = record.send(@attr)
|
|
26
|
+
unless attribute.is_a? Fixnum
|
|
27
|
+
attribute.extend mod
|
|
28
|
+
else
|
|
29
|
+
Fixnum.send(:include, mod)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
alias :after_find :after_initialize
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'active_record'
|
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/user.rb')
|
|
4
|
+
|
|
5
|
+
ActiveRecord::Base.establish_connection(
|
|
6
|
+
:adapter => 'mysql2',
|
|
7
|
+
:host => 'localhost',
|
|
8
|
+
:username => 'root',
|
|
9
|
+
:password => 'admin',
|
|
10
|
+
:database => 'extend_attributes_test',
|
|
11
|
+
:socket => '/var/run/mysqld/mysqld.sock'
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
ActiveRecord::Schema.define do
|
|
15
|
+
drop_table :users rescue nil
|
|
16
|
+
create_table :users do |t|
|
|
17
|
+
t.string :name
|
|
18
|
+
t.integer :work_experience
|
|
19
|
+
t.date :dob
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
data/spec/user.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/date_methods.rb')
|
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/extended_attributes.rb')
|
|
4
|
+
|
|
5
|
+
class User < ActiveRecord::Base
|
|
6
|
+
|
|
7
|
+
extend_attribute :name do
|
|
8
|
+
def first
|
|
9
|
+
self.split(' ').first
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def last
|
|
13
|
+
self.split(' ').last
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
extend_attribute :work_experience do
|
|
18
|
+
|
|
19
|
+
def in_months
|
|
20
|
+
self * 12
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
extend_attribute :dob, :extend => DateMethods
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
end
|
data/spec/user_spec.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
|
|
2
|
+
|
|
3
|
+
describe User do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@user = User.create(
|
|
7
|
+
:name => 'Chirantan Rajhans',
|
|
8
|
+
:work_experience => 3,
|
|
9
|
+
:dob => Date.parse("6th February 1986")
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
it 'should extend name attribute with "first" and "last" methods' do
|
|
15
|
+
@user.name.first.should == 'Chirantan'
|
|
16
|
+
@user.name.last.should == 'Rajhans'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should extend work_experience attribute with "in_months" method' do
|
|
20
|
+
@user.work_experience.in_months.should == 36
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should extend dob attribute with DateMethods module' do
|
|
24
|
+
@user.dob.age.should == 25
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
metadata
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: extended_attributes
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 21
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 1
|
|
8
|
+
- 0
|
|
9
|
+
- 1
|
|
10
|
+
version: 1.0.1
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Chirantan Rajhans
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-10-10 00:00:00 Z
|
|
19
|
+
dependencies:
|
|
20
|
+
- !ruby/object:Gem::Dependency
|
|
21
|
+
name: active_record
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
none: false
|
|
25
|
+
requirements:
|
|
26
|
+
- - <
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
hash: 3
|
|
29
|
+
segments:
|
|
30
|
+
- 3
|
|
31
|
+
- 1
|
|
32
|
+
- 0
|
|
33
|
+
version: 3.1.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
version_requirements: *id001
|
|
36
|
+
description: Extend behavior of attributes of your active record models.
|
|
37
|
+
email: chirantan.rajhans@gmail.com
|
|
38
|
+
executables: []
|
|
39
|
+
|
|
40
|
+
extensions: []
|
|
41
|
+
|
|
42
|
+
extra_rdoc_files: []
|
|
43
|
+
|
|
44
|
+
files:
|
|
45
|
+
- .gitignore
|
|
46
|
+
- Gemfile
|
|
47
|
+
- MIT-LICENSE
|
|
48
|
+
- README.md
|
|
49
|
+
- Rakefile
|
|
50
|
+
- extended_attributes-1.0.0.gem
|
|
51
|
+
- extended_attributes.gemspec
|
|
52
|
+
- lib/extended_attributes.rb
|
|
53
|
+
- spec/date_methods.rb
|
|
54
|
+
- spec/spec_helper.rb
|
|
55
|
+
- spec/user.rb
|
|
56
|
+
- spec/user_spec.rb
|
|
57
|
+
homepage: http://github.com/chirantan
|
|
58
|
+
licenses: []
|
|
59
|
+
|
|
60
|
+
post_install_message:
|
|
61
|
+
rdoc_options: []
|
|
62
|
+
|
|
63
|
+
require_paths:
|
|
64
|
+
- lib
|
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
|
+
none: false
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
hash: 3
|
|
71
|
+
segments:
|
|
72
|
+
- 0
|
|
73
|
+
version: "0"
|
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
|
+
none: false
|
|
76
|
+
requirements:
|
|
77
|
+
- - ">="
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
hash: 3
|
|
80
|
+
segments:
|
|
81
|
+
- 0
|
|
82
|
+
version: "0"
|
|
83
|
+
requirements: []
|
|
84
|
+
|
|
85
|
+
rubyforge_project:
|
|
86
|
+
rubygems_version: 1.8.11
|
|
87
|
+
signing_key:
|
|
88
|
+
specification_version: 3
|
|
89
|
+
summary: Objectify your active record attributes.
|
|
90
|
+
test_files: []
|
|
91
|
+
|