simple_eav 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE +7 -0
- data/README.rdoc +75 -0
- data/Rakefile +1 -0
- data/lib/simple_eav.rb +45 -0
- data/lib/version.rb +3 -0
- data/simple_eav.gemspec +28 -0
- data/spec/db/schema.rb +10 -0
- data/spec/lib/simple_eav_spec.rb +78 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/person.rb +8 -0
- metadata +113 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create ruby-1.9.2-p180@simple_eav
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2011 Tim Linquist
|
2
|
+
|
3
|
+
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:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
= simple_eav
|
2
|
+
|
3
|
+
simple_eav provides a more simple alternative to {acts_as_eav_model}[https://github.com/visfleet/acts_as_eav_model] that works with
|
4
|
+
ActiveRecord without any monkey patching. This gem is designed to be a replacement for acts_as_eav_model.
|
5
|
+
|
6
|
+
Acts_as_eav_model's purpose is to provide a model with any number of custom attributes. This project has the same purpose. The difference being maintaining utmost
|
7
|
+
compatibility with ActiveRecord::Base. For this reason, there is one glaring inconsistency between this gem and acts_as_eav_model.
|
8
|
+
Acts_as_eav_model overrides attributes (among other functionality) to allow you to set any custom attributes. Simple eav does not. I ommitted this in the interest
|
9
|
+
of not having to monkey patch ActiveRecord.
|
10
|
+
|
11
|
+
=== Example
|
12
|
+
person = Person.new {:custom_attribute=>'value'} #This does not work in simple_eav
|
13
|
+
|
14
|
+
person = Person.new {:simple_eav_attributes => {:custom_attribute=>'value'} #This does work in simple_eav
|
15
|
+
person.custom_attribute ~> 'value'
|
16
|
+
|
17
|
+
The latter works because all simple_eav does is use ActiveRecord's built in serialize mechanism to store a hash of custom attributes.
|
18
|
+
So in this example, simple_eav_attributes is a text column in the database for the persons table. Simple eav then takes of
|
19
|
+
serializing the data for this column and defines setters/getters for your custom values.
|
20
|
+
|
21
|
+
This is the only known inconsistency between these two gems. If this is an issue in your project please let me know.
|
22
|
+
|
23
|
+
== Installation
|
24
|
+
gem install simple_eav
|
25
|
+
|
26
|
+
== Usage
|
27
|
+
=== 1. Create the migration for your model
|
28
|
+
|
29
|
+
create_table :people do |t|
|
30
|
+
t.text :custom_attributes # Name this column whatever you like just *make sure* it is a TEXT field
|
31
|
+
....
|
32
|
+
end
|
33
|
+
|
34
|
+
=== 2. Configure simple_eav in your model
|
35
|
+
|
36
|
+
class Person < ActiveRecord::Base
|
37
|
+
include SimpleEav
|
38
|
+
|
39
|
+
configure_simple_eav :custom_attributes # This sets up the serialization for your custom attributes
|
40
|
+
end
|
41
|
+
|
42
|
+
=== 3. Set and Get custom attributes as if they were a normal attribute on your model
|
43
|
+
person = Person.new
|
44
|
+
person.name = 'Joe'
|
45
|
+
person.name ~> 'Joe'
|
46
|
+
|
47
|
+
== Migrating to simple_eav
|
48
|
+
I have not done this yet but will hopefully be making the transition soon. I'll update the README once that's complete or let me know what you find if you migrate your project first.
|
49
|
+
At the moment, a migration would be needed that:
|
50
|
+
- Moves each attribute record to a key => value pair for the simple_eav_column on the model using acts_as_eav_model
|
51
|
+
- Destroys each attribute record
|
52
|
+
|
53
|
+
You'd also need to review where your models using acts_as_eav_model are initialized. If they depended on the single incompatibility mentioned above those calls will need to be updated.
|
54
|
+
|
55
|
+
== Contributing
|
56
|
+
|
57
|
+
* Fork the project.
|
58
|
+
* Make your feature addition or bug fix.
|
59
|
+
* Add tests for it. This is important so I don't break it in a
|
60
|
+
future version unintentionally.
|
61
|
+
* Commit, do not mess with rakefile, version, or history.
|
62
|
+
(if you want to have your own version, that is fine but bump version in a
|
63
|
+
commit by itself I can ignore when I pull)
|
64
|
+
* Send me a pull request. Bonus points for topic branches.
|
65
|
+
|
66
|
+
|
67
|
+
== Author
|
68
|
+
|
69
|
+
{Tim Linquist}[http://github.com/timo3377]
|
70
|
+
|
71
|
+
== Copyright
|
72
|
+
|
73
|
+
Copyright (c) 2011 {Tim Linquist}[http://github.com/timo3377]
|
74
|
+
|
75
|
+
See {LICENSE}[http://github.com/timo3377/simple_eav] for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/simple_eav.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module SimpleEav
|
2
|
+
module ClassMethods
|
3
|
+
def configure_simple_eav(column)
|
4
|
+
@@column = column.to_sym
|
5
|
+
serialize @@column
|
6
|
+
end
|
7
|
+
|
8
|
+
def simple_eav_column
|
9
|
+
@@column if defined? @@column
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
base.extend ClassMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
def simple_eav_column
|
18
|
+
self.class.simple_eav_column
|
19
|
+
end
|
20
|
+
|
21
|
+
def simple_eav_attributes
|
22
|
+
self.send(simple_eav_column.to_sym) || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def simple_eav_attributes=(attributes={})
|
26
|
+
self.send("#{simple_eav_column}=", attributes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def respond_to?(method, include_private=false)
|
30
|
+
super || simple_eav_attributes.has_key?(method)
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method, *args, &block)
|
34
|
+
if method.to_s =~ /=$/
|
35
|
+
_attributes = self.simple_eav_attributes
|
36
|
+
setter = method.to_s.gsub(/=/, '')
|
37
|
+
_attributes[setter.to_sym] = args.shift
|
38
|
+
self.simple_eav_attributes = _attributes
|
39
|
+
elsif simple_eav_attributes.has_key?(method.to_sym)
|
40
|
+
simple_eav_attributes[method.to_sym]
|
41
|
+
else
|
42
|
+
super(method, *args, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/version.rb
ADDED
data/simple_eav.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simple_eav"
|
7
|
+
s.version = SimpleEav::VERSION
|
8
|
+
s.authors = ["Tim Linquist"]
|
9
|
+
s.email = ["tim.linquist@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A simple alternative to acts_as_eav_model.}
|
12
|
+
s.description = %q{A simple alternative to acts_as_eav_model that works with ActiveRecord without any monkey patching needed. Acts_as_eav_model's gives a model the ability to have any number of custom attributes. This project has the same goal. The difference being maintaining utmost compatability with ActiveRecord::Base.}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.extra_rdoc_files = [ "README.rdoc" ]
|
18
|
+
s.require_path = "lib"
|
19
|
+
|
20
|
+
s.add_dependency 'activerecord', '~> 3.0.7'
|
21
|
+
if RUBY_VERSION < '1.9'
|
22
|
+
s.add_development_dependency 'ruby-debug'
|
23
|
+
else
|
24
|
+
s.add_development_dependency 'ruby-debug19'
|
25
|
+
end
|
26
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
27
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
28
|
+
end
|
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleEav do
|
4
|
+
describe "Configuring a model" do
|
5
|
+
it "with the column to serialize" do
|
6
|
+
Person.simple_eav_column.should eql(:simple_attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "serializes the configured column" do
|
10
|
+
p= Person.create({:simple_attributes => {:name=>'John'}})
|
11
|
+
p.simple_attributes[:name].should eql('John')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Expected ActiveRecord behavior" do
|
16
|
+
it "set all of the attributes" do
|
17
|
+
person = Person.create!({
|
18
|
+
:age=>'John Johnson',
|
19
|
+
:simple_attributes=>{
|
20
|
+
:name=>'John'
|
21
|
+
}
|
22
|
+
})
|
23
|
+
person.age.should eql('John Johnson')
|
24
|
+
person.name.should eql('John')
|
25
|
+
end
|
26
|
+
it "serialize and deserialize the simple_eav attributes" do
|
27
|
+
person = Person.new({:simple_attributes=>{
|
28
|
+
:name=>'John'
|
29
|
+
}})
|
30
|
+
person.save!
|
31
|
+
person.reload
|
32
|
+
person.name.should eql('John')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "A missing attribute" do
|
37
|
+
before( :each ) do
|
38
|
+
@person = Person.new
|
39
|
+
end
|
40
|
+
describe "when reading" do
|
41
|
+
it "raises a NoMethodError" do
|
42
|
+
lambda{ @person.unknown_eav }.should raise_error(NoMethodError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
describe "when writing" do
|
46
|
+
it "always defines the attribute without an error" do
|
47
|
+
lambda{ @person.unknown_eav = 'Simple' }.should_not raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "A custom attribute" do
|
53
|
+
describe "John is a Person" do
|
54
|
+
before( :each ) do
|
55
|
+
@person = Person.new
|
56
|
+
end
|
57
|
+
it "who knows his name" do
|
58
|
+
@person.name = 'John'
|
59
|
+
@person.name.should eql('John')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "who can change his name" do
|
63
|
+
@person.name = 'John'
|
64
|
+
@person.name = 'Joe'
|
65
|
+
@person.name.should eql('Joe')
|
66
|
+
end
|
67
|
+
|
68
|
+
it "who responds to his name" do
|
69
|
+
@person.name = 'John'
|
70
|
+
@person.respond_to?(:name).should be_true
|
71
|
+
end
|
72
|
+
|
73
|
+
it "who doesn't respond to someone else's name" do
|
74
|
+
@person.respond_to?(:someone_elses_name).should be_false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
Bundler.setup
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
require 'active_record'
|
8
|
+
require 'sqlite3'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
ActiveRecord::Base.establish_connection({
|
12
|
+
:adapter => 'sqlite3',
|
13
|
+
:database => ":memory:"
|
14
|
+
})
|
15
|
+
load('db/schema.rb')
|
16
|
+
|
17
|
+
$:.push File.expand_path("../lib", __FILE__)
|
18
|
+
require 'support/person'
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.mock_with :rspec
|
22
|
+
end
|
23
|
+
|
24
|
+
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_eav
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Linquist
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-04 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.0.7
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: ruby-debug19
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: sqlite3
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.3
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.6.0
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
description: A simple alternative to acts_as_eav_model that works with ActiveRecord without any monkey patching needed. Acts_as_eav_model's gives a model the ability to have any number of custom attributes. This project has the same goal. The difference being maintaining utmost compatability with ActiveRecord::Base.
|
60
|
+
email:
|
61
|
+
- tim.linquist@gmail.com
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions: []
|
65
|
+
|
66
|
+
extra_rdoc_files:
|
67
|
+
- README.rdoc
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- .rvmrc
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE
|
73
|
+
- README.rdoc
|
74
|
+
- Rakefile
|
75
|
+
- lib/simple_eav.rb
|
76
|
+
- lib/version.rb
|
77
|
+
- simple_eav.gemspec
|
78
|
+
- spec/db/schema.rb
|
79
|
+
- spec/lib/simple_eav_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/support/person.rb
|
82
|
+
homepage: ""
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: "0"
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
requirements: []
|
103
|
+
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.3
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: A simple alternative to acts_as_eav_model.
|
109
|
+
test_files:
|
110
|
+
- spec/db/schema.rb
|
111
|
+
- spec/lib/simple_eav_spec.rb
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- spec/support/person.rb
|