dynattribs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +81 -0
- data/Rakefile +15 -0
- data/dynattribs.gemspec +23 -0
- data/lib/dynattribs.rb +83 -0
- data/lib/dynattribs/version.rb +3 -0
- data/spec/dummy/db/migrate/00001_create_my_test_class.rb +9 -0
- data/spec/dummy/my_test_class.rb +8 -0
- data/spec/dynattribs_spec.rb +25 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/active_record.rb +3 -0
- data/travis.yml +9 -0
- metadata +110 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 James P. McGrath
|
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.rdoc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
= Dynattribs (Dynamic Attributes)
|
2
|
+
Dynattribs makes it easy to declare dynamic attributes in ActiveRecord classes.
|
3
|
+
|
4
|
+
== Overview
|
5
|
+
|
6
|
+
The Dynattribs Gem (Dyanmic Attributes) provide a database backed attributes to
|
7
|
+
ActiveRecord::Base classes, without having to declare table columns for each
|
8
|
+
attribute. A bit of NoSQL data flexibility for traditional database backed
|
9
|
+
ActiveRecord classes.
|
10
|
+
|
11
|
+
The dynamic attributes are stored as a JSON encoded Hash, and can be
|
12
|
+
persisted into any field that can store text data.
|
13
|
+
|
14
|
+
== Installation
|
15
|
+
|
16
|
+
You can use the Dynattribs in your Rails project by including the following in your Gemfile:
|
17
|
+
|
18
|
+
gem 'dynattribs'
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
To use Dynattribs you need to include the mixin in your class definition, preferably at the top.
|
23
|
+
|
24
|
+
To define the names of the dynamic attributes use the "dynamic_attr_accessor"
|
25
|
+
method. This method takes two of more arguments. The first argument is the name
|
26
|
+
of the database field that the dynamic attributes will be persisted to. The other
|
27
|
+
arguments are the names of the dynamic attributes. It is meant to be used in a
|
28
|
+
similar way to the familure "attr_accessor" method
|
29
|
+
|
30
|
+
|
31
|
+
=== Example
|
32
|
+
The following example defines a dynamic "info" field for the MyClass class, with
|
33
|
+
the new info field's data being persisted to the "extra_data" database field.
|
34
|
+
|
35
|
+
class MyClass < < ActiveRecord::Base
|
36
|
+
include Dynattribs
|
37
|
+
|
38
|
+
dynamic_attr_accessor :extra_data, :info
|
39
|
+
end
|
40
|
+
|
41
|
+
=== Database
|
42
|
+
The dynamic attributes are stored converted to a JSON encoded string before storing
|
43
|
+
to the nominated database field. Therefore, you will need to add a string column
|
44
|
+
to the table of any class you wish to add dynamic attributes too.
|
45
|
+
|
46
|
+
A String field would work, but a "text" field would be best due to the large amount
|
47
|
+
of data that could be stored in the dynamic attributes.
|
48
|
+
|
49
|
+
To add the new column, create a migration, e.g.
|
50
|
+
|
51
|
+
rails g migration add_model_dynamic_attribute
|
52
|
+
|
53
|
+
And modify the migration to look something like this:
|
54
|
+
|
55
|
+
class AddModelDynamicAttribute < ActiveRecord::Migration
|
56
|
+
def change
|
57
|
+
add_column :models, :dynamic_attribs, :text
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
== In The Wild
|
62
|
+
|
63
|
+
Dynattribs is used in a number of production systems:
|
64
|
+
|
65
|
+
{Capstory - Private Group Photo Albums }[http://www.capstory.com/]
|
66
|
+
|
67
|
+
{Authic - A Local shopping Sales Notification Service}[http://www.authic.com]
|
68
|
+
|
69
|
+
If you are using Dynattribs in your project and would like to be added to this list, please get in touch!
|
70
|
+
|
71
|
+
== Contributing
|
72
|
+
|
73
|
+
Contributions are very welcome. Please ensure all pull requests include suitable test coverage and all tests are passing.
|
74
|
+
|
75
|
+
== Authors
|
76
|
+
|
77
|
+
* {James McGrath}[https://github.com/jpmcgrath]
|
78
|
+
|
79
|
+
== Licence
|
80
|
+
|
81
|
+
This code is licensed under the MIT license. See MIT-LICENCE for more details.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rdoc/task'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
RSpec::Core::RakeTask.new
|
8
|
+
|
9
|
+
RDoc::Task.new :rdoc do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Dynattribs'
|
12
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
data/dynattribs.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path("../lib/dynattribs/version", __FILE__)
|
2
|
+
|
3
|
+
# Provide a simple gemspec so you can easily use your enginex
|
4
|
+
# project in your rails apps through git.
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dynattribs"
|
7
|
+
s.summary = "Dynattribs makes it easy to declare dynamic attributes in ActiveRecord classes."
|
8
|
+
s.description = "The Dynattribs Gem (Dyanmic Attributes) provide a database backed attributes to ActiveRecord::Base classes, without having to declare table columns for each attribute. A bit of NoSQL data flexibility for traditional database backed ActiveRecord classes."
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.version = Dynattribs::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.authors = [ "James P. McGrath" ]
|
13
|
+
s.email = [ "gems@jamespmcgrath.com" ]
|
14
|
+
s.homepage = "http://jamespmcgrath.com/projects/dynattribs"
|
15
|
+
s.rubyforge_project = "dynattribs"
|
16
|
+
s.required_rubygems_version = "> 1.3.6"
|
17
|
+
#s.add_dependency "rails", ">= 3.0.7"
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "sqlite3"
|
20
|
+
s.add_development_dependency "activerecord"
|
21
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
22
|
+
s.require_path = 'lib'
|
23
|
+
end
|
data/lib/dynattribs.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
module Dynattribs
|
2
|
+
|
3
|
+
############################################################
|
4
|
+
#
|
5
|
+
# PARSE AND ENCODE THE DYNAMIC FIELD DATA
|
6
|
+
# the data is stored to a field defined by "dynamic_attributes_backing_field_name"
|
7
|
+
#
|
8
|
+
############################################################
|
9
|
+
|
10
|
+
# parse and return the json encoded values from the encoded
|
11
|
+
# data stored in the nominated attribute
|
12
|
+
def mapped_data
|
13
|
+
return {} if self[dynamic_attributes_backing_field_name].nil?
|
14
|
+
JSON.parse(self[dynamic_attributes_backing_field_name])
|
15
|
+
end
|
16
|
+
|
17
|
+
# JSON encode and store a hash of attributes
|
18
|
+
def mapped_data=hash
|
19
|
+
self[dynamic_attributes_backing_field_name] = hash.to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
############################################################
|
23
|
+
#
|
24
|
+
# GENERAL GET/SET METHODS
|
25
|
+
#
|
26
|
+
############################################################
|
27
|
+
|
28
|
+
# a general method for retieving a named attribute
|
29
|
+
# from the encoded data
|
30
|
+
def get_dynamic_attr(attr_name)
|
31
|
+
mapped_data[attr_name]
|
32
|
+
end
|
33
|
+
|
34
|
+
# a general method to set the value of the named
|
35
|
+
# attribute in the data map
|
36
|
+
def set_dynamic_attr(attr_name, value)
|
37
|
+
data_map = self.mapped_data
|
38
|
+
data_map[attr_name] = value
|
39
|
+
self.mapped_data = data_map
|
40
|
+
end
|
41
|
+
|
42
|
+
############################################################
|
43
|
+
#
|
44
|
+
# CLASS METHODS
|
45
|
+
#
|
46
|
+
############################################################
|
47
|
+
|
48
|
+
# this bit of ma allows us to "include" class methods (instead of
|
49
|
+
# the normal "extend")with the mixin.
|
50
|
+
# which is needed as the dynamic_attr_accessor method needs
|
51
|
+
# to be invoked as a class method as it is used in the class
|
52
|
+
# definition, rather than from within a instance method
|
53
|
+
def self.included(base)
|
54
|
+
base.extend(ClassMethods)
|
55
|
+
end
|
56
|
+
|
57
|
+
module ClassMethods
|
58
|
+
|
59
|
+
# takes two or more arguments, first arg is the name of the database
|
60
|
+
# field that backs the dynamic fields data hash.
|
61
|
+
# the other arguments are used to create getter/setter methods of
|
62
|
+
# the arguments name.
|
63
|
+
def dynamic_attr_accessor(*args)
|
64
|
+
|
65
|
+
# the first element in the array is the name of the field
|
66
|
+
# used to store the json encoded dynamic attribute data
|
67
|
+
dynamic_attributes_backing_field_name = args.shift
|
68
|
+
# create a method to access this extra data field name
|
69
|
+
self.class_eval("def dynamic_attributes_backing_field_name;'#{dynamic_attributes_backing_field_name}';end") if !dynamic_attributes_backing_field_name.empty?
|
70
|
+
|
71
|
+
# iterate through the rest of the arguments and create
|
72
|
+
# a getter and setter method of each of the desired dynamic attributes
|
73
|
+
args.each do |arg|
|
74
|
+
# getter - creates a wrapper for the get_dynamic_attr method
|
75
|
+
self.class_eval("def #{arg};get_dynamic_attr('#{arg}');end")
|
76
|
+
|
77
|
+
# setter - creates a wrapper for the set_dynamic_attr method
|
78
|
+
self.class_eval("def #{arg}=(val);set_dynamic_attr('#{arg}', val); end")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Dynattribs do
|
5
|
+
|
6
|
+
it "should store and load dynamic attributes" do
|
7
|
+
my_test_class = MyTestClass.new
|
8
|
+
|
9
|
+
my_test_class.info = "This will be stored into info"
|
10
|
+
my_test_class.is_bool = false
|
11
|
+
my_test_class.age = 24
|
12
|
+
my_test_class.tested_at = Time.now
|
13
|
+
|
14
|
+
my_test_class.save.should == true
|
15
|
+
|
16
|
+
loaded_object = MyTestClass.find(my_test_class.id)
|
17
|
+
|
18
|
+
loaded_object.nil?.should == false
|
19
|
+
|
20
|
+
loaded_object.info.should == my_test_class.info
|
21
|
+
loaded_object.is_bool.should == my_test_class.is_bool
|
22
|
+
loaded_object.age.should == my_test_class.age
|
23
|
+
loaded_object.tested_at.should == my_test_class.tested_at
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Configure Rails Envinronment
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
|
4
|
+
require 'dynattribs'
|
5
|
+
require File.expand_path("../dummy/my_test_class.rb", __FILE__)
|
6
|
+
|
7
|
+
# Run any available migration
|
8
|
+
ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
|
data/travis.yml
ADDED
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dynattribs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- James P. McGrath
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
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: sqlite3
|
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
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activerecord
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: The Dynattribs Gem (Dyanmic Attributes) provide a database backed attributes
|
63
|
+
to ActiveRecord::Base classes, without having to declare table columns for each
|
64
|
+
attribute. A bit of NoSQL data flexibility for traditional database backed ActiveRecord
|
65
|
+
classes.
|
66
|
+
email:
|
67
|
+
- gems@jamespmcgrath.com
|
68
|
+
executables: []
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- .gitignore
|
73
|
+
- Gemfile
|
74
|
+
- MIT-LICENSE
|
75
|
+
- README.rdoc
|
76
|
+
- Rakefile
|
77
|
+
- dynattribs.gemspec
|
78
|
+
- lib/dynattribs.rb
|
79
|
+
- lib/dynattribs/version.rb
|
80
|
+
- spec/dummy/db/migrate/00001_create_my_test_class.rb
|
81
|
+
- spec/dummy/my_test_class.rb
|
82
|
+
- spec/dynattribs_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
- spec/support/active_record.rb
|
85
|
+
- travis.yml
|
86
|
+
homepage: http://jamespmcgrath.com/projects/dynattribs
|
87
|
+
licenses: []
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>'
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.3.6
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project: dynattribs
|
106
|
+
rubygems_version: 1.8.24
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Dynattribs makes it easy to declare dynamic attributes in ActiveRecord classes.
|
110
|
+
test_files: []
|