metabolical 0.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 +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +9 -0
- data/README.rdoc +30 -0
- data/Rakefile +27 -0
- data/lib/metabolical.rb +29 -0
- data/lib/metabolical/meta_datum.rb +6 -0
- data/lib/metabolical/scopes.rb +26 -0
- data/lib/metabolical/version.rb +3 -0
- data/metabolical.gemspec +29 -0
- data/test/helper.rb +18 -0
- data/test/metabolical_test.rb +96 -0
- data/test/models/user.rb +5 -0
- data/test/schema/schema.rb +18 -0
- metadata +165 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.8.7
|
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
= Metabolical
|
2
|
+
|
3
|
+
Metabolical is an ActiveRecord Model & mixin that adds metadata to your AR classes.
|
4
|
+
Whenever you feel like adding a column to a table ask yourself if what you really want is just some metadata.
|
5
|
+
|
6
|
+
== Install
|
7
|
+
|
8
|
+
gem install metabolical
|
9
|
+
|
10
|
+
== Usage
|
11
|
+
|
12
|
+
class User < ActiveRecord::Base
|
13
|
+
metabolize!
|
14
|
+
end
|
15
|
+
|
16
|
+
user = User.new
|
17
|
+
user.metas['active'] = true
|
18
|
+
user.metas['active'].data #=> true
|
19
|
+
|
20
|
+
== Notes
|
21
|
+
|
22
|
+
Metabolical will need you to run the following migration
|
23
|
+
|
24
|
+
create_table :meta_data, :force => true do |t|
|
25
|
+
t.integer :metabolized_id
|
26
|
+
t.string :metabolized_type
|
27
|
+
t.string :key
|
28
|
+
t.text :data
|
29
|
+
t.timestamps
|
30
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rubygems/package_task'
|
7
|
+
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
Rake::TestTask.new(:test) do |test|
|
11
|
+
test.libs << 'lib' << 'test'
|
12
|
+
test.pattern = 'test/*_test.rb'
|
13
|
+
test.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
# ROOT = File.expand_path(File.dirname(__FILE__))
|
17
|
+
# TEST_ROOT = ROOT + "/test"
|
18
|
+
# MODELS_ROOT = TEST_ROOT + "/models"
|
19
|
+
# FIXTURES_ROOT = TEST_ROOT + "/fixtures"
|
20
|
+
# MIGRATIONS_ROOT = TEST_ROOT + "/migrations"
|
21
|
+
# SCHEMA_ROOT = TEST_ROOT + "/schema"
|
22
|
+
#
|
23
|
+
# ActiveRecord::Base.establish_connection(
|
24
|
+
# :adapter => "sqlite3",
|
25
|
+
# :database => "db/test.sqlite3"
|
26
|
+
# )
|
27
|
+
# load SCHEMA_ROOT + "/schema.rb"
|
data/lib/metabolical.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'metabolical/meta_datum'
|
2
|
+
require 'metabolical/scopes'
|
3
|
+
|
4
|
+
module Metabolical
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def metabolize!
|
11
|
+
include Metabolical::Scopes
|
12
|
+
|
13
|
+
class_eval do
|
14
|
+
has_many :metas, :as => :metabolized, :class_name => 'Metabolical::MetaDatum' do
|
15
|
+
def [](key)
|
16
|
+
find_by_key(key) || self.proxy_owner.metas.detect{|m| m.key == key}
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key, data)
|
20
|
+
meta = self[key] || self.proxy_owner.metas.build(:key => key)
|
21
|
+
meta.data = data
|
22
|
+
meta
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Metabolical
|
2
|
+
module Scopes
|
3
|
+
def self.included(klass)
|
4
|
+
method = klass.respond_to?(:named_scope) ? :named_scope : :scope
|
5
|
+
klass.send method, :with_meta, lambda{|k| {:joins => [:metas], :conditions => {"meta_data.key" => k}}}
|
6
|
+
klass.send method, :with_metas, :includes => [:metas]
|
7
|
+
klass.send method, :with_meta_data, lambda{|k, v| {:joins => [:metas], :conditions => {"meta_data.key" => k, "meta_data.data" => v.to_yaml}}}
|
8
|
+
klass.send method, :without_meta, lambda{|k|
|
9
|
+
{:joins => [:metas],
|
10
|
+
:conditions => ["meta_data.metabolized_id not in (?)",
|
11
|
+
klass.send(:with_meta, k).all(:select => 'distinct(metabolized_id)').map(&:metabolized_id)]}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
module AR3Scopes
|
16
|
+
def self.included(klass)
|
17
|
+
class_eval do
|
18
|
+
scope :with_meta, lambda{|k| joins([:meta]).where({"meta_data.key" => k}) }
|
19
|
+
scope :with_metas, includes(:meta)
|
20
|
+
scope :with_meta_data, lambda{|k, v| joins(:meta).where("meta_data.key" => k, "meta_data.data" => v.to_yaml)}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/metabolical.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "metabolical/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "metabolical"
|
7
|
+
s.version = Metabolical::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Diego Scataglini"]
|
10
|
+
s.email = ["diego@junivi.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{This is an ActiveRecord Model & mixin to add meta data to any AR object}
|
13
|
+
s.description = %q{This is an ActiveRecord Model & mixin to add meta data to any AR object}
|
14
|
+
|
15
|
+
s.required_ruby_version = '>= 1.8.7'
|
16
|
+
|
17
|
+
s.rubyforge_project = "metabolical"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_dependency('activerecord', '>= 2.1.2')
|
25
|
+
s.add_dependency('activesupport', '>= 2.1.2')
|
26
|
+
s.add_dependency('activemodel', '>= 2.1.2')
|
27
|
+
s.add_dependency('arel', '~> 2.0.10')
|
28
|
+
s.add_dependency('tzinfo', '~> 0.3.23')
|
29
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sqlite3'
|
3
|
+
require 'active_record'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'shoulda'
|
6
|
+
|
7
|
+
TEST_ROOT = File.expand_path(File.dirname(__FILE__))
|
8
|
+
MODELS_ROOT = TEST_ROOT + "/models"
|
9
|
+
FIXTURES_ROOT = TEST_ROOT + "/fixtures"
|
10
|
+
MIGRATIONS_ROOT = TEST_ROOT + "/migrations"
|
11
|
+
SCHEMA_ROOT = TEST_ROOT + "/schema"
|
12
|
+
|
13
|
+
ActiveRecord::Base.establish_connection(
|
14
|
+
:adapter => "sqlite3",
|
15
|
+
:database => "db/test.sqlite3"
|
16
|
+
)
|
17
|
+
|
18
|
+
load SCHEMA_ROOT + "/schema.rb"
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'models/user'
|
3
|
+
|
4
|
+
class MetabolicalTest < Test::Unit::TestCase
|
5
|
+
context "an ActiveRecord Object" do
|
6
|
+
|
7
|
+
context "new record" do
|
8
|
+
setup do
|
9
|
+
@user = User.new
|
10
|
+
end
|
11
|
+
|
12
|
+
teardown do
|
13
|
+
@user.destroy
|
14
|
+
end
|
15
|
+
|
16
|
+
should "be able to assign a single meta before saving and retrieving it after save" do
|
17
|
+
@user.metas['foo'] = 'bar'
|
18
|
+
@user.save
|
19
|
+
assert_equal 'bar', @user.metas['foo'].data
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be able to assign a single meta before saving and retrieving it before save" do
|
23
|
+
@user.metas['foo'] = 'bar'
|
24
|
+
assert_equal 'bar', @user.metas['foo'].data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "saved record" do
|
29
|
+
setup do
|
30
|
+
@user = User.new
|
31
|
+
@user.save
|
32
|
+
end
|
33
|
+
|
34
|
+
teardown do
|
35
|
+
@user.destroy
|
36
|
+
end
|
37
|
+
|
38
|
+
should "be able to assign a single meta before re saving and retrieving it after save" do
|
39
|
+
@user.metas['foo'] = 'bar'
|
40
|
+
@user.save
|
41
|
+
assert_equal 'bar', @user.metas['foo'].data
|
42
|
+
end
|
43
|
+
|
44
|
+
should "be able to assign a single meta before re saving and retrieving it before save" do
|
45
|
+
@user.metas['foo'] = 'baz'
|
46
|
+
assert_equal 'baz', @user.metas['foo'].data
|
47
|
+
end
|
48
|
+
|
49
|
+
should "be able to retrieve after saving" do
|
50
|
+
@user.metas['foo'] = 'faz'
|
51
|
+
@user.save
|
52
|
+
user = User.find @user.id
|
53
|
+
assert_equal 'faz', user.metas['foo'].data
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context "named scopes" do
|
59
|
+
setup do
|
60
|
+
@foo_user = User.create(:name => 'foo_user', :metas => [Metabolical::MetaDatum.new(:key => "foo", :data => "bar")])
|
61
|
+
@bar_user = User.create(:name => 'bar_user', :metas => [Metabolical::MetaDatum.new(:key => "bar", :data => "baz"),
|
62
|
+
Metabolical::MetaDatum.new(:key => "fuu", :data => "bar")])
|
63
|
+
@true_user = User.create(:name => 'true_user', :metas => [Metabolical::MetaDatum.new(:key => "bar", :data => true)])
|
64
|
+
end
|
65
|
+
|
66
|
+
teardown do
|
67
|
+
User.delete_all
|
68
|
+
end
|
69
|
+
|
70
|
+
should "have with_meta scopes" do
|
71
|
+
assert_equal [@foo_user], User.with_meta("foo")
|
72
|
+
assert_equal [@bar_user, @true_user], User.with_meta("bar")
|
73
|
+
end
|
74
|
+
|
75
|
+
should "have with_meta scopes that check for data" do
|
76
|
+
assert_equal [], User.with_meta_data("foo", "foo")
|
77
|
+
assert_equal [@foo_user], User.with_meta_data("foo", "bar"), "Should have brought back foo user"
|
78
|
+
assert_equal [@true_user], User.with_meta_data("bar", true), "Should have brought back true user"
|
79
|
+
end
|
80
|
+
|
81
|
+
should "have with_metas scope that includes all metas" do
|
82
|
+
assert User.respond_to?(:with_metas)
|
83
|
+
end
|
84
|
+
|
85
|
+
should "bring back objects without a certain meta" do
|
86
|
+
assert_equal [@foo_user], User.without_meta("bar")
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
data/test/models/user.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
|
3
|
+
create_table :users, :force => true do |t|
|
4
|
+
t.string :name
|
5
|
+
t.timestamps
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :meta_data, :force => true do |t|
|
9
|
+
t.integer :metabolized_id
|
10
|
+
t.string :metabolized_type
|
11
|
+
t.string :key
|
12
|
+
t.text :data
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :meta_data, [:metabolized_id, :metabolized_type, :key]
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: metabolical
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Diego Scataglini
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-07-03 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activerecord
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 15
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 1
|
33
|
+
- 2
|
34
|
+
version: 2.1.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: activesupport
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 15
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 1
|
49
|
+
- 2
|
50
|
+
version: 2.1.2
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: activemodel
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 1
|
65
|
+
- 2
|
66
|
+
version: 2.1.2
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: arel
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 27
|
78
|
+
segments:
|
79
|
+
- 2
|
80
|
+
- 0
|
81
|
+
- 10
|
82
|
+
version: 2.0.10
|
83
|
+
type: :runtime
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: tzinfo
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 61
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 3
|
97
|
+
- 23
|
98
|
+
version: 0.3.23
|
99
|
+
type: :runtime
|
100
|
+
version_requirements: *id005
|
101
|
+
description: This is an ActiveRecord Model & mixin to add meta data to any AR object
|
102
|
+
email:
|
103
|
+
- diego@junivi.com
|
104
|
+
executables: []
|
105
|
+
|
106
|
+
extensions: []
|
107
|
+
|
108
|
+
extra_rdoc_files: []
|
109
|
+
|
110
|
+
files:
|
111
|
+
- .gitignore
|
112
|
+
- .rvmrc
|
113
|
+
- Gemfile
|
114
|
+
- README.rdoc
|
115
|
+
- Rakefile
|
116
|
+
- lib/metabolical.rb
|
117
|
+
- lib/metabolical/meta_datum.rb
|
118
|
+
- lib/metabolical/scopes.rb
|
119
|
+
- lib/metabolical/version.rb
|
120
|
+
- metabolical.gemspec
|
121
|
+
- test/helper.rb
|
122
|
+
- test/metabolical_test.rb
|
123
|
+
- test/models/user.rb
|
124
|
+
- test/schema/schema.rb
|
125
|
+
has_rdoc: true
|
126
|
+
homepage: ""
|
127
|
+
licenses: []
|
128
|
+
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 57
|
140
|
+
segments:
|
141
|
+
- 1
|
142
|
+
- 8
|
143
|
+
- 7
|
144
|
+
version: 1.8.7
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
hash: 3
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
version: "0"
|
154
|
+
requirements: []
|
155
|
+
|
156
|
+
rubyforge_project: metabolical
|
157
|
+
rubygems_version: 1.3.7
|
158
|
+
signing_key:
|
159
|
+
specification_version: 3
|
160
|
+
summary: This is an ActiveRecord Model & mixin to add meta data to any AR object
|
161
|
+
test_files:
|
162
|
+
- test/helper.rb
|
163
|
+
- test/metabolical_test.rb
|
164
|
+
- test/models/user.rb
|
165
|
+
- test/schema/schema.rb
|