acts_as_metadata 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: