acts_as_metadata 0.1.0

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 ADDED
@@ -0,0 +1 @@
1
+ db/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in metadata.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,105 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ acts_as_metadata (0.0.2)
5
+ rails (>= 3.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionmailer (3.1.3)
11
+ actionpack (= 3.1.3)
12
+ mail (~> 2.3.0)
13
+ actionpack (3.1.3)
14
+ activemodel (= 3.1.3)
15
+ activesupport (= 3.1.3)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ i18n (~> 0.6)
19
+ rack (~> 1.3.5)
20
+ rack-cache (~> 1.1)
21
+ rack-mount (~> 0.8.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.0.3)
24
+ activemodel (3.1.3)
25
+ activesupport (= 3.1.3)
26
+ builder (~> 3.0.0)
27
+ i18n (~> 0.6)
28
+ activerecord (3.1.3)
29
+ activemodel (= 3.1.3)
30
+ activesupport (= 3.1.3)
31
+ arel (~> 2.2.1)
32
+ tzinfo (~> 0.3.29)
33
+ activeresource (3.1.3)
34
+ activemodel (= 3.1.3)
35
+ activesupport (= 3.1.3)
36
+ activesupport (3.1.3)
37
+ multi_json (~> 1.0)
38
+ arel (2.2.1)
39
+ builder (3.0.0)
40
+ diff-lcs (1.1.3)
41
+ erubis (2.7.0)
42
+ hike (1.2.1)
43
+ i18n (0.6.0)
44
+ json (1.6.1)
45
+ mail (2.3.0)
46
+ i18n (>= 0.4.0)
47
+ mime-types (~> 1.16)
48
+ treetop (~> 1.4.8)
49
+ mime-types (1.17.2)
50
+ multi_json (1.0.3)
51
+ polyglot (0.3.3)
52
+ rack (1.3.5)
53
+ rack-cache (1.1)
54
+ rack (>= 0.4)
55
+ rack-mount (0.8.3)
56
+ rack (>= 1.0.0)
57
+ rack-ssl (1.3.2)
58
+ rack
59
+ rack-test (0.6.1)
60
+ rack (>= 1.0)
61
+ rails (3.1.3)
62
+ actionmailer (= 3.1.3)
63
+ actionpack (= 3.1.3)
64
+ activerecord (= 3.1.3)
65
+ activeresource (= 3.1.3)
66
+ activesupport (= 3.1.3)
67
+ bundler (~> 1.0)
68
+ railties (= 3.1.3)
69
+ railties (3.1.3)
70
+ actionpack (= 3.1.3)
71
+ activesupport (= 3.1.3)
72
+ rack-ssl (~> 1.3.2)
73
+ rake (>= 0.8.7)
74
+ rdoc (~> 3.4)
75
+ thor (~> 0.14.6)
76
+ rake (0.9.2.2)
77
+ rdoc (3.11)
78
+ json (~> 1.4)
79
+ rspec (2.7.0)
80
+ rspec-core (~> 2.7.0)
81
+ rspec-expectations (~> 2.7.0)
82
+ rspec-mocks (~> 2.7.0)
83
+ rspec-core (2.7.1)
84
+ rspec-expectations (2.7.0)
85
+ diff-lcs (~> 1.1.2)
86
+ rspec-mocks (2.7.0)
87
+ sprockets (2.0.3)
88
+ hike (~> 1.2)
89
+ rack (~> 1.0)
90
+ tilt (~> 1.1, != 1.3.0)
91
+ sqlite3 (1.3.4)
92
+ thor (0.14.6)
93
+ tilt (1.3.3)
94
+ treetop (1.4.10)
95
+ polyglot
96
+ polyglot (>= 0.3.1)
97
+ tzinfo (0.3.31)
98
+
99
+ PLATFORMS
100
+ ruby
101
+
102
+ DEPENDENCIES
103
+ acts_as_metadata!
104
+ rspec (>= 2.0.0)
105
+ sqlite3
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/Readme ADDED
@@ -0,0 +1,11 @@
1
+ ActsAsMetadata
2
+ ==============
3
+
4
+ User-generated metadata fields for your Rails models.
5
+
6
+ Usage
7
+ -----
8
+
9
+ class MyModel < ActiveRecord::Base
10
+ acts_as_metadata
11
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "metadata/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "acts_as_metadata"
7
+ s.version = ActsAsMetadata::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Gropher"]
10
+ s.email = ["grophen@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Additional on-demand fields for ActiveRecord models}
13
+ s.description = %q{This gem allows to add additional database-stored fields to your models}
14
+
15
+ s.rubyforge_project = "acts_as_metadata"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_dependency('rails', '>= 3.0.0' )
22
+ s.add_development_dependency("rspec", ">= 2.0.0")
23
+ s.add_development_dependency("sqlite3")
24
+ end
@@ -0,0 +1,20 @@
1
+ require "active_record"
2
+ require "action_view"
3
+
4
+ require 'metadata/metadata'
5
+ require 'metadata/metadata_type'
6
+ require 'metadata/acts_as_metadata'
7
+ require 'metadata/acts_as_metadata_helper'
8
+ require 'metadata/version'
9
+
10
+ if defined?(ActiveRecord::Base)
11
+ ActiveRecord::Base.extend ActsAsMetadata
12
+ end
13
+
14
+ module ApplicationHelper
15
+ include ActsAsMetadataHelper
16
+ end
17
+
18
+ module ActsAsMetadata
19
+ # Your code goes here...
20
+ end
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Metadata
5
+ class MigrationGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ def self.source_root
9
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
10
+ end
11
+
12
+
13
+ def self.next_migration_number(dirname)
14
+ #if ActiveRecord::Base.timestamped_migrations
15
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
16
+ "%.3d" % (current_migration_number(dirname) + 1)
17
+ #end
18
+ end
19
+
20
+ def create_migration_file
21
+ migration_template 'migration.rb', 'db/migrate/create_metadata.rb'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ class CreateMetadata < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :metadata do |t|
4
+ t.column :id, :integer
5
+ t.column :metadata_type, :string
6
+ t.column :model_id, :integer
7
+ t.column :model_type, :string
8
+ t.column :value, :text
9
+ t.column :search_value, :string
10
+
11
+ t.timestamp :deleted_at, :default => nil
12
+ t.timestamps
13
+ end
14
+
15
+ create_table :metadata_types do |t|
16
+ t.column :id, :integer
17
+ t.column :name, :string
18
+ t.column :description, :text
19
+ t.column :tag, :string
20
+ t.column :datatype, :string, :default => "string"
21
+ t.column :mandatory, :boolean, :default => false
22
+ t.column :format, :string
23
+ t.column :values, :text
24
+ t.column :models, :string, :default => '--- []'
25
+ t.column :default, :text
26
+
27
+ t.timestamp :deleted_at, :default => nil
28
+ t.timestamps
29
+ end
30
+
31
+ add_index :metadata_types, :datatype
32
+ add_index :metadata_types, :tag, :unique => true
33
+ add_index :metadata, :metadata_type
34
+ add_index :metadata, [:metadata_type, :search_value]
35
+ add_index :metadata, [:model_id, :model_type]
36
+ end
37
+
38
+ def self.down
39
+ drop_table :metadata
40
+ drop_table :metadata_types
41
+ end
42
+ end
@@ -0,0 +1,132 @@
1
+ module ActsAsMetadata
2
+ def acts_as_metadata(options={})
3
+ if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
4
+ scope = "#{options[:scope]}_id".to_sym
5
+ else
6
+ scope = nil
7
+ end
8
+
9
+ MetadataType.class_variable_set("@@metadata_scope", scope)
10
+ class_variable_set("@@metadata_scope", scope)
11
+ class_eval do
12
+ serialize :metadata_cache
13
+ has_many :metadata, :as => :model, :dependent => :destroy, :class_name => "Metadata::Metadata"
14
+ before_create :create_accessors_and_save_metadata
15
+ before_update :create_accessors_and_save_metadata
16
+ validate :metadata_constraints
17
+
18
+ def metadata_constraints
19
+ metadata_types.each do |type_name|
20
+ type = MetadataType.type(type_name, metadata_scope)
21
+ value = get_metadata(type.tag)
22
+ values = type.values.map {|v| v.is_a?(Array) ? v[1] : v } rescue []
23
+ errors.add(type.tag, I18n.t('acts_as_metadata.errors.blank')) if type.mandatory && value.blank?
24
+ errors.add(type.tag, I18n.t('acts_as_metadata.errors.format')) if !type.format.blank? && !value.blank? && value.to_s !~ Regexp.new("^#{type.format}$")
25
+ errors.add(type.tag, I18n.t('acts_as_metadata.errors.values')) if !values.blank? && !value.blank? && !values.include?(value)
26
+ end unless @skip_metadata_validation
27
+ end
28
+
29
+ def skip_metadata_validation!
30
+ @skip_metadata_validation = true
31
+ end
32
+
33
+
34
+ def mass_assignment_authorizer(role = :default)
35
+ super + metadata_types
36
+ end
37
+
38
+ def initialize(args=nil, options = {})
39
+ scope = self.class.class_variable_get('@@metadata_scope') ? args[self.class.class_variable_get('@@metadata_scope')] : nil rescue nil
40
+ types = MetadataType.model_types(model_name, scope)
41
+ types.each do |type|
42
+ create_accessor type
43
+ end
44
+ super
45
+ end
46
+
47
+ def update_attributes(attributes)
48
+ create_accessors
49
+ super
50
+ end
51
+
52
+ def create_accessors
53
+ metadata_types.each do |type|
54
+ create_accessor type
55
+ end
56
+ end
57
+
58
+ def create_accessor type
59
+ class_eval "attr_accessor :#{type}"
60
+ class_eval "def #{type}; get_metadata('#{type}'); end"
61
+ class_eval "def #{type}=(value); set_metadata('#{type}', value); end"
62
+ end
63
+
64
+ def create_accessors_and_save_metadata
65
+ create_accessors
66
+ save_metadata
67
+ end
68
+
69
+ def method_missing(meth, *args, &block)
70
+ begin
71
+ super
72
+ rescue NoMethodError
73
+ name = meth.to_s
74
+ if name =~ /^(.+)=$/
75
+ name = name[0..-2]
76
+ if metadata_types.include?(name)
77
+ set_metadata(name, args.first)
78
+ else
79
+ raise
80
+ end
81
+ else
82
+ if metadata_types.include?(name)
83
+ get_metadata(name)
84
+ else
85
+ raise
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def metadata_scope
92
+ self.class.class_variable_get('@@metadata_scope') ? self.send(self.class.class_variable_get('@@metadata_scope')) : nil
93
+ end
94
+
95
+ def model_name
96
+ self.class.name.underscore.to_sym
97
+ end
98
+
99
+ def metadata_types
100
+ MetadataType.model_types(model_name, metadata_scope)
101
+ end
102
+
103
+ def self.metadata_types(scope=nil)
104
+ MetadataType.model_types(self.name.underscore.to_sym, scope)
105
+ end
106
+
107
+ def get_metadata(name)
108
+ load_metadata unless metadata_cache.is_a?(Hash)
109
+ metadata_cache[name]
110
+ end
111
+
112
+ def set_metadata(name, value)
113
+ type = MetadataType.type(name, metadata_scope)
114
+ raise NoMethodError if type.nil?
115
+ load_metadata unless metadata_cache.is_a?(Hash)
116
+ self.metadata_cache[name] = type.type_cast(value) || type.type_cast(type.default)
117
+ end
118
+
119
+ def save_metadata
120
+ Metadata::Metadata.delete_all(:model_type => self.class.name, :model_id => self.id) unless self.id.blank?
121
+ self.metadata_types.each do |type_name|
122
+ value = self.get_metadata(type_name)
123
+ self.metadata.build(:metadata_type => type_name, :value => value) unless value.nil?
124
+ end
125
+ end
126
+
127
+ def load_metadata
128
+ self.metadata_cache = Hash[self.metadata.all.map { |m| [m.metadata_type, m.value] }]
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,37 @@
1
+ module ActsAsMetadataHelper
2
+ def metadata_type_datatype_names
3
+ return MetadataType::DATATYPES.map { |key, value| [t("activerecord.attributes.metadata_type.datatypes.#{value}"), key] }
4
+ end
5
+
6
+ def metadata_type_form_fields(f)
7
+ res = ""
8
+ f.object.metadata_types.each do |tag|
9
+ type = MetadataType.type(tag)
10
+ res += f.label(type.name)
11
+ case type.datatype
12
+ when "boolean"
13
+ res += f.check_box(type.tag)
14
+ when "text"
15
+ res += f.text_area(type.tag)
16
+ when "datetime"
17
+ res += f.text_field(type.tag)
18
+ when "date"
19
+ res += f.text_field(type.tag)
20
+ when "number"
21
+ res += f.text_field(type.tag)
22
+ when "string"
23
+ res += f.text_field(type.tag)
24
+ end
25
+ end
26
+ res.html_safe
27
+ end
28
+
29
+ def metadata_type_datatype_name(type)
30
+ return t("activerecord.attributes.metadata_type.datatypes.#{MetadataType::DATATYPES[type.datatype.to_sym]}")
31
+ end
32
+
33
+
34
+ def metadata_type_mandatory_name(type)
35
+ return t("activerecord.attributes.metadata_type.mandatory_values.#{type.mandatory}")
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module Metadata
2
+ class Metadata < ActiveRecord::Base
3
+ default_scope :conditions => {:deleted_at => nil}, :order => 'created_at DESC'
4
+ before_save :set_search_value
5
+
6
+ def undelete
7
+ self.deleted_at=nil
8
+ self.save
9
+ end
10
+
11
+ def destroy(real = false)
12
+ if real
13
+ Metadata.unscoped.delete_all(:id => self.id)
14
+ else
15
+ self.run_callbacks(:destroy)
16
+ self.update_attribute(:deleted_at, Time.now.utc)
17
+ end
18
+ end
19
+
20
+ protected
21
+ def set_search_value
22
+ self.search_value = value.to_s[0,255] rescue nil
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,148 @@
1
+ class MetadataType < ActiveRecord::Base
2
+ DATATYPES = {
3
+ :string => "string",
4
+ :text => "text",
5
+ :date => "date",
6
+ :datetime => "datetime",
7
+ :number => "number",
8
+ :boolean => "boolean",
9
+ :array => "array"
10
+ }
11
+
12
+ serialize :default
13
+ serialize :values
14
+ serialize :models
15
+ after_create :set_default_values
16
+ after_update :refresh_metadata
17
+ before_destroy :refresh_metadata
18
+ attr_accessor :models_json, :values_json, :default_json
19
+ attr_accessible :tag, :name, :description, :models, :mandatory,
20
+ :default, :format, :datatype, :values,
21
+ :models_json, :values_json, :default_json
22
+ validates :tag, :presence => true, :format => {:with => /^[a-z]+[a-z0-9]*$/},
23
+ :exclusion => { :in => %w(format errors callback action categorie accept attributes host key layout notify open render save template type id parent_id lft rgt test select),
24
+ :message => "this name is reserved"}
25
+ validates :datatype, :presence => true
26
+ default_scope :conditions => {:deleted_at => nil}, :order => 'created_at DESC'
27
+
28
+ def self.default
29
+ self.new({
30
+ :tag => :sample,
31
+ :name => "Sample",
32
+ :models => [:any],
33
+ :mandatory => false,
34
+ :default => 'default',
35
+ :datatype => "string",
36
+ :format => nil,
37
+ :values => nil
38
+ })
39
+ end
40
+
41
+ def type_cast(value)
42
+ return nil if value.nil?
43
+ return value unless value.is_a? String
44
+ case datatype
45
+ when 'date'
46
+ ActiveRecord::ConnectionAdapters::Column.string_to_date value
47
+ when 'datetime'
48
+ ActiveRecord::ConnectionAdapters::Column.string_to_time value
49
+ when 'number'
50
+ Integer value
51
+ when 'boolean'
52
+ ActiveRecord::ConnectionAdapters::Column.value_to_boolean value
53
+ else
54
+ value
55
+ end rescue nil
56
+ end
57
+
58
+ def models_json
59
+ self.models ? self.models.to_json : [].to_json
60
+ end
61
+
62
+ def models_json=(value)
63
+ self.models = JSON.parse(value) rescue []
64
+ end
65
+
66
+ def values_json
67
+ self.values ? self.values.to_json : [].to_json
68
+ end
69
+
70
+ def values_json=(value)
71
+ self.values = JSON.parse(value) rescue []
72
+ end
73
+
74
+ def default_json
75
+ self.default.to_json
76
+ end
77
+
78
+ def default_json=(value)
79
+ self.default = JSON.parse(value) rescue value[/"(.*)"/, 1]
80
+ end
81
+
82
+ def self.scheme_data(scope=nil)
83
+ Rails.cache.fetch("metadata_scheme_#{@@metadata_scope}#{scope}_data", :expires_in => 60.minutes) do
84
+ uncached do
85
+ scheme_data = scope.blank? ? self.all : self.where(@@metadata_scope => scope).all
86
+ if scheme_data.count > 0
87
+ scheme_data
88
+ else
89
+ []
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ def self.scheme(scope=nil)
96
+ Rails.cache.fetch("metadata_scheme_#{@@metadata_scope}#{scope}_types", :expires_in => 60.minutes) do
97
+ res = {}
98
+ self.scheme_data(scope).each do |type|
99
+ res[type.tag] = type
100
+ end
101
+ res
102
+ end
103
+ end
104
+
105
+ def self.model_types(model, scope=nil)
106
+ types = Rails.cache.fetch("metadata_scheme_#{@@metadata_scope}#{scope}_modeltypes", :expires_in => 60.minutes) do
107
+ res = { :any => [] }
108
+ self.scheme(scope).each do |tag, type|
109
+ type.models.each do |model|
110
+ res[model] = [] if res[model].blank?
111
+ res[model] << tag
112
+ end if type.models
113
+ end
114
+ res
115
+ end
116
+ types[model] ? (types[model] | types[:any]).uniq : types[:any]
117
+ end
118
+
119
+ def self.type(name, scope=nil)
120
+ self.scheme(scope)[name]
121
+ end
122
+
123
+ def self.drop_cache(scope=nil)
124
+ Rails.cache.delete("metadata_scheme_#{@@metadata_scope}#{scope}_data")
125
+ Rails.cache.delete("metadata_scheme_#{@@metadata_scope}#{scope}_types")
126
+ Rails.cache.delete("metadata_scheme_#{@@metadata_scope}#{scope}_modeltypes")
127
+ end
128
+
129
+ private
130
+ def set_default_values
131
+ self.models = [] if self.models.nil?
132
+ self.values = [] if self.values.nil?
133
+ self.save
134
+ if @@metadata_scope
135
+ MetadataType.drop_cache(self.send(@@metadata_scope))
136
+ else
137
+ MetadataType.drop_cache
138
+ end
139
+ end
140
+
141
+ def refresh_metadata
142
+ if @@metadata_scope
143
+ MetadataType.drop_cache(self.send(@@metadata_scope))
144
+ else
145
+ MetadataType.drop_cache
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,3 @@
1
+ module ActsAsMetadata
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ class MyModel < ActiveRecord::Base
4
+ acts_as_metadata
5
+ end
6
+
7
+ describe ActsAsMetadata do
8
+ it 'creates metadata_type' do
9
+ MetadataType.default.save!
10
+ MetadataType.scheme_data.count.should == 1
11
+ end
12
+
13
+ it 'has default metadata value' do
14
+ mymodel = MyModel.create
15
+ mymodel.sample.should == 'default'
16
+ end
17
+
18
+ it 'set metadata value' do
19
+ mymodel = MyModel.new
20
+ mymodel.sample = 'test'
21
+ mymodel.save!
22
+ mymodel = MyModel.last
23
+ mymodel.sample.should == 'test'
24
+ end
25
+
26
+ it 'updates metadata value' do
27
+ mymodel = MyModel.last
28
+ mymodel.sample = 'test2'
29
+ mymodel.save!
30
+ mymodel = MyModel.last
31
+ mymodel.sample.should == 'test2'
32
+ end
33
+
34
+ it 'detete metadata when model deleted' do
35
+ MyModel.destroy_all
36
+ Metadata::Metadata.all.count.should == 0
37
+ end
38
+
39
+ it 'check presence validation' do
40
+ mt = MetadataType.first
41
+ mt.mandatory = true
42
+ mt.default = nil
43
+ mt.save!
44
+ mymodel = MyModel.new
45
+ mymodel.save
46
+ mymodel.errors.include?(:sample).should == true
47
+ mymodel.sample = 'wqwewew'
48
+ mymodel.save
49
+ mymodel.errors.count.should == 0
50
+ end
51
+
52
+ it 'check format validation' do
53
+ mt = MetadataType.first
54
+ mt.mandatory = false
55
+ mt.format = '[a-z]'
56
+ mt.save!
57
+ mymodel = MyModel.new
58
+ mymodel.sample = '12323'
59
+ mymodel.save
60
+ mymodel.errors.include?(:sample).should == true
61
+ mymodel.sample = 'wqwewew'
62
+ mymodel.save
63
+ mymodel.errors.count.should == 0
64
+ end
65
+
66
+ it 'check values validation' do
67
+ mt = MetadataType.first
68
+ mt.values = ['aaa', 'bbb']
69
+ mt.save!
70
+ mymodel = MyModel.new
71
+ mymodel.sample = 'ccc'
72
+ mymodel.save
73
+ mymodel.errors.include?(:sample).should == true
74
+ mymodel.sample = 'bbb'
75
+ mymodel.save
76
+ mymodel.errors.count.should == 0
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'rails/all'
5
+ require 'acts_as_metadata' # and any other gems you need
6
+
7
+ root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "sqlite3",
10
+ :database => "#{root}/db/acts_as_metadata.db"
11
+ )
12
+ ActionController::Base.cache_store = ActiveSupport::Cache::MemoryStore.new
13
+ RAILS_CACHE = ActionController::Base.cache_store
14
+
15
+ RSpec.configure do |config|
16
+ # some (optional) config here
17
+ end
18
+
19
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'my_models'")
20
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'metadata'")
21
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'metadata_types'")
22
+ ActiveRecord::Base.connection.create_table(:my_models) do |t|
23
+ t.integer :id
24
+ t.string :name
25
+ t.text :description
26
+ t.text :metadata_cache
27
+ t.datetime "created_at"
28
+ t.datetime "updated_at"
29
+ end
30
+ ActiveRecord::Base.connection.create_table(:metadata) do |t|
31
+ t.string "metadata_type"
32
+ t.integer "model_id"
33
+ t.string "model_type"
34
+ t.text "value"
35
+ t.datetime "deleted_at"
36
+ t.datetime "created_at"
37
+ t.datetime "updated_at"
38
+ end
39
+ ActiveRecord::Base.connection.create_table(:metadata_types) do |t|
40
+ t.string "name"
41
+ t.text "description"
42
+ t.string "tag"
43
+ t.string "datatype", :default => "string"
44
+ t.boolean "mandatory", :default => false
45
+ t.string "format"
46
+ t.text "values"
47
+ t.string "models", :default => "--- []"
48
+ t.text "default"
49
+ t.datetime "deleted_at"
50
+ t.datetime "created_at"
51
+ t.datetime "updated_at"
52
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_metadata
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gropher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.0.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: 2.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: sqlite3
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: This gem allows to add additional database-stored fields to your models
63
+ email:
64
+ - grophen@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - Rakefile
73
+ - Readme
74
+ - acts_as_metadata.gemspec
75
+ - lib/acts_as_metadata.rb
76
+ - lib/generators/metadata/migration/migration_generator.rb
77
+ - lib/generators/metadata/migration/templates/migration.rb
78
+ - lib/metadata/acts_as_metadata.rb
79
+ - lib/metadata/acts_as_metadata_helper.rb
80
+ - lib/metadata/metadata.rb
81
+ - lib/metadata/metadata_type.rb
82
+ - lib/metadata/version.rb
83
+ - spec/acts_as_metadata_spec.rb
84
+ - spec/spec_helper.rb
85
+ homepage: ''
86
+ licenses: []
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project: acts_as_metadata
105
+ rubygems_version: 1.8.24
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Additional on-demand fields for ActiveRecord models
109
+ test_files: []
110
+ has_rdoc: