tableless_model 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +50 -0
- data/README.rdoc +97 -0
- data/Rakefile +2 -0
- data/lib/activerecord/base/class_methods.rb +97 -0
- data/lib/tableless_model/class_methods.rb +81 -0
- data/lib/tableless_model/instance_methods.rb +80 -0
- data/lib/tableless_model/version.rb +3 -0
- data/lib/tableless_model.rb +30 -0
- data/spec/tableless_model_spec.rb +8 -0
- data/tableless_model.gemspec +27 -0
- metadata +134 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tableless_model (0.0.1)
|
5
|
+
activerecord
|
6
|
+
hashie
|
7
|
+
validatable
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activemodel (3.0.3)
|
13
|
+
activesupport (= 3.0.3)
|
14
|
+
builder (~> 2.1.2)
|
15
|
+
i18n (~> 0.4)
|
16
|
+
activerecord (3.0.3)
|
17
|
+
activemodel (= 3.0.3)
|
18
|
+
activesupport (= 3.0.3)
|
19
|
+
arel (~> 2.0.2)
|
20
|
+
tzinfo (~> 0.3.23)
|
21
|
+
activesupport (3.0.3)
|
22
|
+
arel (2.0.6)
|
23
|
+
builder (2.1.2)
|
24
|
+
diff-lcs (1.1.2)
|
25
|
+
hashie (0.4.0)
|
26
|
+
i18n (0.5.0)
|
27
|
+
mocha (0.9.10)
|
28
|
+
rake
|
29
|
+
rake (0.8.7)
|
30
|
+
rspec (2.3.0)
|
31
|
+
rspec-core (~> 2.3.0)
|
32
|
+
rspec-expectations (~> 2.3.0)
|
33
|
+
rspec-mocks (~> 2.3.0)
|
34
|
+
rspec-core (2.3.1)
|
35
|
+
rspec-expectations (2.3.0)
|
36
|
+
diff-lcs (~> 1.1.2)
|
37
|
+
rspec-mocks (2.3.0)
|
38
|
+
tzinfo (0.3.23)
|
39
|
+
validatable (1.6.7)
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
activerecord
|
46
|
+
hashie
|
47
|
+
mocha
|
48
|
+
rspec
|
49
|
+
tableless_model!
|
50
|
+
validatable
|
data/README.rdoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
= Tableless Model
|
2
|
+
|
3
|
+
This is an extended Hash that has a defined collection of method-like attributes, and only these attributes can be set or read from the hash.
|
4
|
+
Optionally, you can also set default values and enforce data types for these attributes.
|
5
|
+
|
6
|
+
Tableless Model behaves in a similar way to normal ActiveRecord models in that it also supports validations and can be useful, for example, to reduce database complexity in some cases, by removing associations and therefore tables.
|
7
|
+
|
8
|
+
In particular, by using Tableless Model, you could save tables whenever you have one to one associations between a parent model and a child model containing options, settings, debugging information or any other collection of attributes that belongs uniquely to a single parent object.
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
== Installation
|
13
|
+
|
14
|
+
Tableless Model is available as a Rubygem:
|
15
|
+
|
16
|
+
gem install tableless_model
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
== Usage
|
21
|
+
|
22
|
+
For example's sake, say we have these two models:
|
23
|
+
|
24
|
+
1)
|
25
|
+
|
26
|
+
class Page < ActiveRecord::Base
|
27
|
+
|
28
|
+
# having columns such as id, title, etc
|
29
|
+
|
30
|
+
has_one :seo_settings
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
2)
|
35
|
+
|
36
|
+
class SeoOptions < ActiveRecord::Base
|
37
|
+
|
38
|
+
set_table_name "seo_options"
|
39
|
+
|
40
|
+
# having columns such as id, title_tag, meta_description, meta_keywords,
|
41
|
+
# noindex, nofollow, noarchive, page_id
|
42
|
+
|
43
|
+
belongs_to :page
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
So that each instance of Page has its own SEO options, and these options/settings only belong to a page, so we have a one to one association, and our database will have the tables "pages", and "seo_options".
|
49
|
+
|
50
|
+
Using Tableless Model, we could remove the association and the table seo_options altogether, by storing those options in a column in the pages table, in a YAML::serialized form. So the models become:
|
51
|
+
|
52
|
+
|
53
|
+
1)
|
54
|
+
|
55
|
+
class Page < ActiveRecord::Base
|
56
|
+
|
57
|
+
# having columns such as id, title, seo, etc
|
58
|
+
|
59
|
+
has_tableless :seo => SeoOptions
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
2)
|
64
|
+
|
65
|
+
class SeoOptions < ActiveRecord::TablelessModel
|
66
|
+
|
67
|
+
attribute :title_tag, :type => :string, :default => ""
|
68
|
+
attribute :meta_description, :type => :string, :default => ""
|
69
|
+
attribute :meta_keywords, :type => :string, :default => ""
|
70
|
+
attribute :noindex, :type => :boolean, :default => false
|
71
|
+
attribute :nofollow, :type => :boolean, :default => false
|
72
|
+
attribute :noarchive, :type => :boolean, :default => false
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
That's it. Each instance of Page will now store directly its YAML-serialized SEO settings in the column named "seo". This is how the content of that column would look like in the database:
|
78
|
+
|
79
|
+
--- !map:SeoOptions
|
80
|
+
noarchive: false
|
81
|
+
meta_description:
|
82
|
+
meta_keywords:
|
83
|
+
nofollow: false
|
84
|
+
title_tag:
|
85
|
+
noindex: false
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
== TODO
|
90
|
+
|
91
|
+
* Support for associations
|
92
|
+
|
93
|
+
|
94
|
+
== Authors
|
95
|
+
|
96
|
+
* Vito Botta ( http://vitobotta.com )
|
97
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Base
|
2
|
+
module ClassMethods
|
3
|
+
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# Macro to attach a tableless model to a parent, table-based model.
|
7
|
+
# The parent model is expected to own a property/column having as name the first argument
|
8
|
+
# (or the key if the argument is a hash )
|
9
|
+
#
|
10
|
+
# Can be used this way:
|
11
|
+
#
|
12
|
+
# class Parent < ActiveRecord::Base
|
13
|
+
#
|
14
|
+
# has_tableless :settings
|
15
|
+
#
|
16
|
+
# # or...
|
17
|
+
#
|
18
|
+
# has_tableless :settings => ParentSettings
|
19
|
+
#
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# NOTE: the serialized column is expected to be of type string or text in the database
|
24
|
+
#
|
25
|
+
def has_tableless(column)
|
26
|
+
column_name = column.class == Hash ? column.collect{|k,v| k}.first.to_sym : column
|
27
|
+
|
28
|
+
# if only the column name is given, the tableless model's class is expected to have that name, classified, as class name
|
29
|
+
class_type = column.class == Hash ? column.collect{|k,v| v}.last : column.to_s.classify.constantize
|
30
|
+
|
31
|
+
|
32
|
+
# injecting in the parent object a getter and a setter for the
|
33
|
+
# attribute that will store an instance of a tableless model
|
34
|
+
class_eval do
|
35
|
+
|
36
|
+
# Making sure the serialized column contains a new instance of the tableless model
|
37
|
+
# if it hasn't been set yet
|
38
|
+
default_value_for column_name => class_type.new
|
39
|
+
|
40
|
+
# Telling AR that the column has to store an instance of the given tableless model in
|
41
|
+
# YAML serialized format
|
42
|
+
serialize column_name, ActiveRecord::TablelessModel
|
43
|
+
|
44
|
+
# Adding getter for the serialized column,
|
45
|
+
# making sure it always returns an instance of the specified tableless
|
46
|
+
# model and not just a normal hash or the value of the attribute in the database,
|
47
|
+
# which is plain text
|
48
|
+
define_method column_name.to_s do
|
49
|
+
class_type.new(read_attribute(class_name.to_sym) || {})
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adding setter for the serialized column,
|
53
|
+
# making sure it always stores in it an instance of
|
54
|
+
# the specified tableless model (as the argument may also be a regular hash)
|
55
|
+
define_method "#{column_name.to_s}=" do |value|
|
56
|
+
super class_type.new(value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
#
|
63
|
+
#
|
64
|
+
# Overriding the setter for the serialized column in the AR model,
|
65
|
+
# to make sure that, if it is still nil, the column always
|
66
|
+
# returns at least a new instance of the specified tableless model
|
67
|
+
# having the default values, if any, declared in the tableless model itself
|
68
|
+
#
|
69
|
+
def default_value_for(property, default_value)
|
70
|
+
unless method_defined? "after_initialize_with_default_value_for_#{property.to_s}"
|
71
|
+
|
72
|
+
unless method_defined? "after_initialize"
|
73
|
+
define_method "after_initialize" do |*args|
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
define_method "after_initialize_with_default_value_for_#{property.to_s}" do |*args|
|
78
|
+
send("after_initialize_without_default_value_for_#{property.to_s}", *args)
|
79
|
+
return unless new_record?
|
80
|
+
return unless self.respond_to?(property.to_sym)
|
81
|
+
|
82
|
+
self.send("#{property.to_s}=".to_sym, self.send(property.to_sym) || default_value)
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method_chain "after_initialize", "default_value_for_#{property.to_s}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# Extending ActiveRecord::Base class with a macro required by the Tableless model,
|
94
|
+
# and another one that can be used to serialize a tableless model instance into
|
95
|
+
# a parent object's column
|
96
|
+
|
97
|
+
ActiveRecord::Base.extend Base::ClassMethods
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Tableless
|
2
|
+
module ClassMethods
|
3
|
+
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# Macro to define an attribute of the Tableless model.
|
7
|
+
# To be used as follows in a tableless model:
|
8
|
+
#
|
9
|
+
# class Example < ActiveRecord::TablelessModel
|
10
|
+
#
|
11
|
+
# attribute :name, :type => :string
|
12
|
+
# attribute :active, :type => :boolean, :default => true
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
#
|
17
|
+
def attribute(name, options = {})
|
18
|
+
# Stringifies all keys... uses a little more memory but it's a bit easier to handle keys internally...
|
19
|
+
attribute_name = name.to_s
|
20
|
+
|
21
|
+
# Defining the new attribute for the tableless model
|
22
|
+
self.attributes[attribute_name] = options
|
23
|
+
|
24
|
+
# Defining method-like getter and setter for the new attribute
|
25
|
+
# so it can be used like a regular object's property
|
26
|
+
class_eval %Q{
|
27
|
+
def #{attribute_name}
|
28
|
+
self["#{attribute_name}"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def #{attribute_name}=(value)
|
32
|
+
self["#{attribute_name}"] = value
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
#
|
39
|
+
#
|
40
|
+
# Initialises @attributes in the context of the class inheriting from the Tableless model
|
41
|
+
#
|
42
|
+
def inherited(klass)
|
43
|
+
super
|
44
|
+
(@subclasses ||= Set.new) << klass
|
45
|
+
klass.instance_variable_set("@attributes", Hash.new)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
#
|
50
|
+
#
|
51
|
+
# If a data type has been specified for an attribute, its value
|
52
|
+
# will be converted accordingly (if necessary) when getting or setting it
|
53
|
+
#
|
54
|
+
#
|
55
|
+
def cast(attribute_name, value)
|
56
|
+
return nil if value.nil?
|
57
|
+
|
58
|
+
type = self.attributes[attribute_name.to_s][:type]
|
59
|
+
|
60
|
+
return value if type.nil?
|
61
|
+
|
62
|
+
begin
|
63
|
+
case type
|
64
|
+
when :string then (value.is_a?(String) ? value : String(value))
|
65
|
+
when :integer then (value.is_a?(Integer) ? value : Integer(value))
|
66
|
+
when :float then (value.is_a?(Float) ? value : Float(value))
|
67
|
+
when :decimal then (value.is_a?(Float) ? value : Float(value))
|
68
|
+
when :time then (value.is_a?(Time) ? value : Time.parse(value))
|
69
|
+
when :date then (value.is_a?(Date) ? value : Date.parse(value))
|
70
|
+
when :datetime then (value.is_a?(DateTime) ? value : DateTime.parse(value))
|
71
|
+
when :boolean then (value == true || value == 1 || value.to_s =~ /^(true|1)$/i)
|
72
|
+
else value
|
73
|
+
end
|
74
|
+
rescue Exception => e
|
75
|
+
raise StandardError, "Invalid value '#{value.inspect}' for attribute #{attribute_name} - expected data type is #{type} but value is a #{value.class} (Exception details: #{e})"
|
76
|
+
value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Tableless
|
2
|
+
module InstanceMethods
|
3
|
+
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# On initialising an instance of a tableless model,
|
7
|
+
# sets the default values for all the attributes defined.
|
8
|
+
# Optionally, initialises the tableless model with the values
|
9
|
+
# specified as arguments, instead, overriding the default values
|
10
|
+
#
|
11
|
+
#
|
12
|
+
def initialize(init_attributes = {}, &block)
|
13
|
+
super &block
|
14
|
+
|
15
|
+
self.class.attributes.each_pair {|attribute_name, options| self.send("#{attribute_name}=", options[:default])}
|
16
|
+
init_attributes.each_pair {|k,v| self.send("#{k}=", v)} if init_attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# Returns true if the method name specified corresponds
|
23
|
+
# to the key of an attribute defined for the tableless model
|
24
|
+
#
|
25
|
+
#
|
26
|
+
def respond_to?(method_name)
|
27
|
+
key?(method_name) ? true : super
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# Overriding getter for the underlying hash keys
|
34
|
+
# so that only the defined attributes can be read
|
35
|
+
#
|
36
|
+
def [](attribute_name)
|
37
|
+
raise NoMethodError, "The attribute #{attribute_name} is undefined" unless self.class.attributes.has_key? attribute_name.to_s
|
38
|
+
self.class.cast(attribute_name, super(attribute_name.to_s))
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
#
|
44
|
+
# Overriding setter for the underlying hash keys
|
45
|
+
# so that only the defined attributes can be set
|
46
|
+
#
|
47
|
+
def []=(attribute_name, value)
|
48
|
+
raise NoMethodError, "The attribute #{attribute_name} is undefined" unless self.class.attributes.has_key? attribute_name.to_s
|
49
|
+
super attribute_name.to_s, self.class.cast(attribute_name, value)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# The Hash object displays inspect information in the format
|
56
|
+
#
|
57
|
+
# "{:a=>1, :b=>2}"
|
58
|
+
#
|
59
|
+
# to make the tableless model look a bit more like regular models,
|
60
|
+
# it shows instead the inspect information in this format:
|
61
|
+
#
|
62
|
+
# "<#MyTablelessModel a=1 b=2>"
|
63
|
+
#
|
64
|
+
def inspect
|
65
|
+
"<##{self.class.to_s}" << self.keys.sort.inject(""){|result, k| result << " #{k}=#{self[k].inspect}"; result } << ">"
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# Ensures that when merging with a given hash
|
72
|
+
# all the keys are stringified as the keys are always handled
|
73
|
+
# as strings in the tableless model
|
74
|
+
#
|
75
|
+
def merge(hash)
|
76
|
+
super hash.stringify_keys
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "validatable"
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "activerecord/base/class_methods"))
|
3
|
+
|
4
|
+
Dir[File.join(File.dirname(__FILE__), "tableless_model/*rb")].each {|f| require File.expand_path(f)}
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
|
8
|
+
# TablelessModel class is basically an Hash with method-like keys that must be defined in advance
|
9
|
+
# as for an ActiveRecord model, but without a table. Trying to set new keys not defined at class level
|
10
|
+
# result in NoMethodError raised
|
11
|
+
|
12
|
+
class TablelessModel < Hash
|
13
|
+
|
14
|
+
extend Tableless::ClassMethods
|
15
|
+
include Tableless::InstanceMethods
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# Exposes an accessors that will store the names of the attributes defined for the Tableless model,
|
20
|
+
# and their default values
|
21
|
+
# This accessor is an instance of Set defined in the inheriting class (see self.inherited)
|
22
|
+
#
|
23
|
+
#
|
24
|
+
class << self
|
25
|
+
attr_reader :attributes
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "tableless_model/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "tableless_model"
|
7
|
+
s.version = TablelessModel::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Vito Botta"]
|
10
|
+
s.email = ["vito@botta.name"]
|
11
|
+
s.homepage = "http://rubygems.org/gems/tableless_model"
|
12
|
+
s.summary = %q{A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object}
|
13
|
+
s.description = %q{A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object}
|
14
|
+
|
15
|
+
s.add_dependency "hashie"
|
16
|
+
s.add_dependency "validatable"
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "mocha"
|
20
|
+
|
21
|
+
s.rubyforge_project = "tableless_model"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tableless_model
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Vito Botta
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-02 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: hashie
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: validatable
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: mocha
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
77
|
+
description: A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object
|
78
|
+
email:
|
79
|
+
- vito@botta.name
|
80
|
+
executables: []
|
81
|
+
|
82
|
+
extensions: []
|
83
|
+
|
84
|
+
extra_rdoc_files: []
|
85
|
+
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- Gemfile
|
89
|
+
- Gemfile.lock
|
90
|
+
- README.rdoc
|
91
|
+
- Rakefile
|
92
|
+
- lib/activerecord/base/class_methods.rb
|
93
|
+
- lib/tableless_model.rb
|
94
|
+
- lib/tableless_model/class_methods.rb
|
95
|
+
- lib/tableless_model/instance_methods.rb
|
96
|
+
- lib/tableless_model/version.rb
|
97
|
+
- spec/tableless_model_spec.rb
|
98
|
+
- tableless_model.gemspec
|
99
|
+
has_rdoc: true
|
100
|
+
homepage: http://rubygems.org/gems/tableless_model
|
101
|
+
licenses: []
|
102
|
+
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
hash: 3
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
hash: 3
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
requirements: []
|
127
|
+
|
128
|
+
rubyforge_project: tableless_model
|
129
|
+
rubygems_version: 1.4.1
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object
|
133
|
+
test_files:
|
134
|
+
- spec/tableless_model_spec.rb
|