has_metadata 1.6.1 → 1.6.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e2f29c8739a41a97beed0ed3c6b331f8ba3cc2da4ee8bacbd7dc269a0113d23a
4
+ data.tar.gz: 9ceb1f806883a0a42a8734270801b88f715357fb8315f8dbf51566d84a4caaad
5
+ SHA512:
6
+ metadata.gz: 91d5b70471591f8c37c8ae7d6849e370356b6f0fb42c324b7e5a451c0b3448564060f178be7c1ec853f53d4302f8eb2acd7ad1f0d13270fd69bd4ac0a19dfc57
7
+ data.tar.gz: a53e2493826bd95af4c129a6fa3b4a73acfee451f1b70797d48fa4803242662d54bda4324b7627204a90718fbc2db65edec46efb60f8fa13d7d38a1ef1ee4736
data/README.md ADDED
@@ -0,0 +1,117 @@
1
+ > ⚠️ **DEPRECATED:** `has_metadata` is no longer maintained. Superseded by
2
+ > [`has_metadata_column`](https://github.com/RISCfuture/has_metadata_column)
3
+ > (also deprecated). No active maintenance. The final release is v1.6.2.
4
+
5
+ has_metadata
6
+ ============
7
+
8
+ **Keep your tables narrow**
9
+
10
+ | | |
11
+ |:------------|:--------------------------------|
12
+ | **Author** | Tim Morgan |
13
+ | **Version** | 1.6.1 (Jan 24, 2012) |
14
+ | **License** | Released under the MIT License. |
15
+
16
+ About
17
+ -----
18
+
19
+ Wide tables are a problem for big databases. If your `ActiveRecord` models have
20
+ 10, maybe 15 columns, some of which are `VARCHARs` or maybe even `TEXTs`, it's
21
+ going to slow your queries down when you start to scale up.
22
+
23
+ The easy solution to this problem is to limit your projections; in other words,
24
+ to only `SELECT` the columns that you actually need. If you've got a `users`
25
+ table with a giant `about_me` text column, and you're only trying to look up the
26
+ user's login, then just select the `login` column.
27
+
28
+ In the long run, though, a superior solution is to just move those
29
+ `about_me`-type columns to a completely different table. This table has just one
30
+ JSON-serialized field, making it schemaless, so it doesn't waste space. Each row
31
+ in this table is associated with a record in another table (`Metadata` `has_one`
32
+ of your models).
33
+
34
+ This way, when your website gets huge, all of your giant, freeform data is in
35
+ one table that you can shard, or move off to an alternate database, or even a
36
+ NoSQL-type document store, or otherwise manage as you please. Your relational
37
+ tables remain slim and efficient, containing only columns that a) are indexed,
38
+ or b) you need frequent access to.
39
+
40
+ This gem includes a generator that creates the `Metadata` model, and a module
41
+ that you can include in your models to define which fields have been spun off to
42
+ the metadata record.
43
+
44
+ Installation
45
+ ------------
46
+
47
+ **Important Note:** This gem is only compatible with Ruby 1.9+ and Rails 3.0+.
48
+
49
+ Firstly, add the gem to your Rails project's `Gemfile`:
50
+
51
+ ```` ruby
52
+ gem 'has_metadata'
53
+ ````
54
+
55
+ Next, run the generator, which will add the `Metadata` model and its migration
56
+ to your application.
57
+
58
+ ```` sh
59
+ rails generate metadata
60
+ ````
61
+
62
+ Usage
63
+ -----
64
+
65
+ The first thing to think about is what columns to keep in your model. You will
66
+ need to keep any indexed columns, or any columns you perform lookups or other
67
+ SQL queries with. You should also keep any frequently accessed columns,
68
+ especially if they are small (integers or booleans). Good candidates for the
69
+ metadata table are the `TEXT`- and `VARCHAR`-type columns that you only need to
70
+ render a page or two in your app.
71
+
72
+ You'll need to change your model's schema so that it has a `metadata_id` column
73
+ that will associate the model with its `Metadata` instance:
74
+
75
+ ```` ruby
76
+ t.belongs_to :metadata
77
+ ````
78
+
79
+ Next, include the `HasMetadata` module in your model, and call the
80
+ `has_metadata` method to define the schema of your metadata. You can get more
81
+ information in the {HasMetadata::ClassMethods#has_metadata} documentation, but for starters, here's a
82
+ basic example:
83
+
84
+ ```` ruby
85
+ class User < ActiveRecord::Base
86
+ include HasMetadata
87
+ has_metadata({
88
+ about_me: { type: String, length: { maximum: 512 } },
89
+ birthdate: { type: Date, presence: true },
90
+ zipcode: { type: Number, numericality: { greater_than: 9999, less_than: 10_000} }
91
+ })
92
+ end
93
+ ````
94
+
95
+ As you can see, you pass field names mapped to a hash. The hash describes the
96
+ validation that will be performed, and is in the same format as a call to
97
+ `validates`. In addition to the `EachValidator` keys shown above, you can also
98
+ pass a `type` key, to constrain the Ruby type that can be assigned to the field.
99
+
100
+ Each of these fields (in this case, `about_me`, `birthdate`, and `zipcode`) can
101
+ be accessed and set as first_level methods on an instance of your model:
102
+
103
+ ```` ruby
104
+ user.about_me #=> "I was born in 1982 in Aberdeen. My father was a carpenter from..."
105
+ ````
106
+
107
+ ... and thus, used as part of `form_for` fields:
108
+
109
+ ```` ruby
110
+ form_for user do |f|
111
+ f.text_area :about_me, rows: 5, cols: 80
112
+ end
113
+ ````
114
+
115
+ The only thing you _can't_ do is use these fields in a query, obviously. You
116
+ can't do something like `User.where(zipcode: 90210)`, because that column
117
+ doesn't exist on the `users` table.
data/has_metadata.gemspec CHANGED
@@ -2,23 +2,24 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: has_metadata 1.6.2 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "has_metadata"
8
- s.version = "1.6.1"
9
+ s.version = "1.6.2"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
12
  s.authors = ["Tim Morgan"]
12
- s.date = "2012-01-25"
13
+ s.date = "2013-12-08"
13
14
  s.description = "has_metadata lets you move non-indexed and weighty columns off of your big tables by creating a separate metadata table to store all this extra information. Works with Ruby 1.9. and Rails 3.0."
14
15
  s.email = "git@timothymorgan.info"
15
16
  s.extra_rdoc_files = [
16
17
  "LICENSE",
17
- "README.textile"
18
+ "README.md"
18
19
  ]
19
20
  s.files = [
20
21
  "LICENSE",
21
- "README.textile",
22
+ "README.md",
22
23
  "has_metadata.gemspec",
23
24
  "lib/has_metadata.rb",
24
25
  "lib/has_metadata/metadata_generator.rb",
@@ -29,11 +30,20 @@ Gem::Specification.new do |s|
29
30
  s.homepage = "http://github.com/riscfuture/has_metadata"
30
31
  s.require_paths = ["lib"]
31
32
  s.required_ruby_version = Gem::Requirement.new(">= 1.9")
32
- s.rubygems_version = "1.8.15"
33
- s.summary = "Reduce your table width by moving non-indexed columns to a separate metadata table"
33
+ s.rubygems_version = "2.1.11"
34
+ s.summary = "[DEPRECATED] Reduce your table width by moving non-indexed columns to a separate metadata table"
35
+ s.post_install_message = <<~MSG
36
+
37
+ ⚠️ DEPRECATED: has_metadata is no longer maintained.
38
+
39
+ Superseded by `has_metadata_column` (also deprecated as of this notice). No active maintenance.
40
+
41
+ This is the final release. No further updates are planned.
42
+
43
+ MSG
34
44
 
35
45
  if s.respond_to? :specification_version then
36
- s.specification_version = 3
46
+ s.specification_version = 4
37
47
 
38
48
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
49
  s.add_runtime_dependency(%q<rails>, [">= 3.2"])
@@ -5,19 +5,19 @@ require 'rails/generators/migration'
5
5
  # @private
6
6
  class MetadataGenerator < Rails::Generators::Base
7
7
  include Rails::Generators::Migration
8
-
8
+
9
9
  source_root "#{File.dirname __FILE__}/../../templates"
10
-
10
+
11
11
  def self.next_migration_number(dirname)
12
12
  if ActiveRecord::Base.timestamped_migrations then
13
- Time.now.utc.strftime "%Y%m%d%H%M%S"
13
+ Time.now.utc.strftime '%Y%m%d%H%M%S'
14
14
  else
15
15
  "%.3d" % (current_migration_number(dirname) + 1)
16
16
  end
17
17
  end
18
-
18
+
19
19
  def copy_files
20
- copy_file "metadata.rb", "app/models/metadata.rb"
21
- migration_template "create_metadata.rb", "db/migrate/create_metadata.rb"
20
+ copy_file 'metadata.rb', 'app/models/metadata.rb'
21
+ migration_template 'create_metadata.rb', 'db/migrate/create_metadata.rb'
22
22
  end
23
23
  end
@@ -1,9 +1,11 @@
1
+ require 'active_record'
2
+
1
3
  module HasMetadata
2
-
4
+
3
5
  # Base class of the {Metadata} model. Functionality is moved to this class to
4
- # make changes to the model easier. See the @Metadata@ method for more
6
+ # make changes to the model easier. See the `Metadata` method for more
5
7
  # information.
6
-
8
+
7
9
  class Model < ActiveRecord::Base
8
10
  self.table_name = 'metadata'
9
11
  serialize :data, Hash
@@ -20,10 +22,10 @@ module HasMetadata
20
22
  name = name.to_sym
21
23
  super(name) or fields.include?(name)
22
24
  end
23
-
25
+
24
26
  # override attribute prefix/suffix methods to get full first-class
25
27
  # property functionality
26
-
28
+
27
29
  singleton_class.send(:define_method, :attribute) do |name|
28
30
  name = name.to_sym
29
31
  super(name) unless fields.include?(name)
@@ -33,7 +35,7 @@ module HasMetadata
33
35
  data.include?(name) ? data[name] : default
34
36
  end
35
37
  singleton_class.send :alias_method, :attribute_before_type_cast, :attribute
36
-
38
+
37
39
  singleton_class.send(:define_method, :query_attribute) do |name|
38
40
  name = name.to_sym
39
41
  super(name) unless fields.include?(name)
@@ -49,7 +51,7 @@ module HasMetadata
49
51
  not send(name).blank?
50
52
  end
51
53
  end
52
-
54
+
53
55
  singleton_class.send(:define_method, :attribute=) do |name, value|
54
56
  name = name.to_sym
55
57
  super(name, value) unless fields.include?(name)
data/lib/has_metadata.rb CHANGED
@@ -16,15 +16,16 @@ class Object
16
16
  end
17
17
 
18
18
 
19
- # Provides the {ClassMethods#has_metadata} method to subclasses of @ActiveRecord::Base@.
19
+ # Provides the {ClassMethods#has_metadata} method to subclasses of
20
+ # `ActiveRecord::Base`.
20
21
 
21
22
  module HasMetadata
22
23
  extend ActiveSupport::Concern
23
-
24
+
24
25
  # @private
25
26
  def self.metadata_typecast(value, type)
26
27
  if value.kind_of?(String) then
27
- if type == Integer or type == Fixnum then
28
+ if type == Integer or type == Integer then
28
29
  begin
29
30
  return Integer(value.sub(/^0+/, '')) # so that it doesn't think it's in octal
30
31
  rescue ArgumentError
@@ -36,33 +37,37 @@ module HasMetadata
36
37
  rescue ArgumentError
37
38
  return value
38
39
  end
39
- elsif type == Boolean then return value.parse_bool end
40
+ elsif type == Boolean then
41
+ return value.parse_bool
42
+ end
40
43
  end
41
44
  return value
42
45
  end
43
-
46
+
44
47
  # Class methods that are added to your model.
45
-
48
+
46
49
  module ClassMethods
47
50
 
48
51
  # Defines a set of fields whose values exist in the associated {Metadata}
49
- # record. Each key in the @fields@ hash is the name of a metadata field, and
50
- # the value is a set of options to pass to the @validates@ method. If you do
51
- # not want to perform any validation on a field, simply pass @true@ as its
52
+ # record. Each key in the `fields` hash is the name of a metadata field, and
53
+ # the value is a set of options to pass to the `validates` method. If you do
54
+ # not want to perform any validation on a field, simply pass `true` as its
52
55
  # key value.
53
56
  #
54
- # In addition to the normal @validates@ keys, you can also include a @:type@
55
- # key to restrict values to certain classes, or a @:default@ key to specify
57
+ # In addition to the normal `validates` keys, you can also include a `:type`
58
+ # key to restrict values to certain classes, or a `:default` key to specify
56
59
  # a value to return for the getter should none be set (normal default is
57
- # @nil@).
60
+ # `nil`).
58
61
  #
59
62
  # @param [Hash<Symbol, Hash>] fields A mapping of field names to their
60
- # validation options (and/or the @:type@ key).
63
+ # validation options (and/or the `:type` key).
61
64
  #
62
65
  # @example Three metadata fields, one basic, one validated, and one type-checked.
63
- # has_metadata(optional: true, required: { presence: true }, number: { type: Fixnum })
66
+ # has_metadata(optional: true, required: { presence: true }, number: { type: Integer })
64
67
 
65
68
  def has_metadata(fields)
69
+ raise "Can't define Rails-magic timestamped columns as metadata" if (fields.keys & [:created_at, :created_on, :updated_at, :updated_on]).any?
70
+
66
71
  if !respond_to?(:metadata_fields) then
67
72
  belongs_to :metadata, dependent: :destroy
68
73
  accepts_nested_attributes_for :metadata
@@ -74,9 +79,8 @@ module HasMetadata
74
79
  define_method(:save_metadata) { metadata.save! }
75
80
  define_method(:metadata_changed?) { metadata.try :changed? }
76
81
 
77
- alias_method_chain :changed_attributes, :metadata
78
- alias_method_chain :attribute_will_change!, :metadata
79
- else
82
+ prepend WithMetadata
83
+ elsif metadata_fields.slice(*fields.keys) != fields
80
84
  raise "Cannot redefine existing metadata fields: #{(fields.keys & self.metadata_fields.keys).to_sentence}" unless (fields.keys & self.metadata_fields.keys).empty?
81
85
  self.metadata_fields = self.metadata_fields.merge(fields)
82
86
  end
@@ -84,33 +88,34 @@ module HasMetadata
84
88
  fields.each do |name, options|
85
89
  # delegate all attribute methods to the metadata
86
90
  attribute_method_matchers.each { |matcher| delegate matcher.method_name(name), to: :metadata! }
87
-
91
+
88
92
  if options.kind_of?(Hash) then
89
- type = options.delete(:type)
93
+ type = options.delete(:type)
90
94
  type_validate = !options.delete(:skip_type_validation)
91
95
  options.delete :default
92
-
96
+
93
97
  validate do |obj|
94
98
  value = obj.send(name)
95
- errors.add(name, :incorrect_type) unless
96
- HasMetadata.metadata_typecast(value, type).kind_of?(type) or
99
+ errors.add(name, :incorrect_type) unless HasMetadata.metadata_typecast(value, type).kind_of?(type) or
97
100
  ((options[:allow_nil] and value.nil?) or (options[:allow_blank] and value.blank?))
98
101
  end if type && type_validate
99
- validates(name, options) unless options.empty? or (options.keys - [ :allow_nil, :allow_blank ]).empty?
102
+ validates(name, options) unless options.empty? or (options.keys - [:allow_nil, :allow_blank]).empty?
100
103
  end
101
104
  end
102
105
  end
103
106
  end
104
107
 
108
+ # @private
105
109
  def as_json(options={})
106
- options ||= Hash.new # the JSON encoder can sometimes give us nil options?
107
- options[:except] = Array.wrap(options[:except]) + [ :metadata_id ]
110
+ options ||= Hash.new # the JSON encoder can sometimes give us nil options?
111
+ options[:except] = Array.wrap(options[:except]) + [:metadata_id]
108
112
  options[:methods] = Array.wrap(options[:methods]) + metadata_fields.keys - options[:except].map(&:to_sym)
109
113
  super options
110
114
  end
111
-
115
+
116
+ # @private
112
117
  def to_xml(options={})
113
- options[:except] = Array.wrap(options[:except]) + [ :metadata_id ]
118
+ options[:except] = Array.wrap(options[:except]) + [:metadata_id]
114
119
  options[:methods] = Array.wrap(options[:methods]) + metadata_fields.keys - options[:except].map(&:to_sym)
115
120
  super options
116
121
  end
@@ -118,18 +123,20 @@ module HasMetadata
118
123
  # @private
119
124
  def assign_multiparameter_attributes(pairs)
120
125
  fake_attributes = pairs.select { |(field, _)| self.class.metadata_fields.include? field[0, field.index('(')].to_sym }
126
+ result = super(pairs.except(fake_attributes.keys))
121
127
 
122
128
  fake_attributes.group_by { |(field, _)| field[0, field.index('(')] }.each do |field_name, parts|
123
129
  options = self.class.metadata_fields[field_name.to_sym]
124
130
  if options[:type] then
125
131
  args = parts.each_with_object([]) do |(part_name, value), ary|
126
132
  part_ann = part_name[part_name.index('(') + 1, part_name.length]
127
- index = part_ann.to_i - 1
133
+ index = part_ann.to_i - 1
128
134
  raise "Out-of-bounds multiparameter argument index" unless index >= 0
129
135
  ary[index] = if value.blank? then nil
130
- elsif part_ann.ends_with?('i)') then value.to_i
131
- elsif part_ann.ends_with?('f)') then value.to_f
132
- else value end
136
+ elsif part_ann.ends_with?('i)') then value.to_i
137
+ elsif part_ann.ends_with?('f)') then value.to_f
138
+ else value
139
+ end
133
140
  end
134
141
  args.compact!
135
142
  send :"#{field_name}=", options[:type].new(*args) unless args.empty?
@@ -138,7 +145,7 @@ module HasMetadata
138
145
  end
139
146
  end
140
147
 
141
- super(pairs - fake_attributes)
148
+ return result
142
149
  end
143
150
 
144
151
  # @return [Metadata] An existing associated {Metadata} instance, or new,
@@ -158,20 +165,27 @@ module HasMetadata
158
165
 
159
166
  # @private
160
167
  def inspect
161
- "#<#{self.class.to_s} #{attributes.merge(metadata.try(:data).try(:stringify_keys) || {}).map { |k,v| "#{k}: #{v.inspect}" }.join(', ')}>"
168
+ "#<#{self.class.to_s} #{attributes.merge(metadata.try(:data).try(:stringify_keys) || {}).map { |k, v| "#{k}: #{v.inspect}" }.join(', ')}>"
162
169
  end
163
170
 
164
- # @private
165
- def changed_attributes_with_metadata
166
- changed_attributes_without_metadata.merge(metadata.try(:changed_metadata) || {})
167
- end
171
+ module WithMetadata
172
+ # @private
173
+ def changed_attributes
174
+ super.merge(metadata.try(:changed_metadata) || {})
175
+ end
168
176
 
169
- # @private
170
- def attribute_will_change_with_metadata!(attr)
171
- if attribute_names.include?(attr) then
172
- attribute_will_change_without_metadata! attr
173
- else
174
- metadata!.send :attribute_will_change!, attr
177
+ # @private
178
+ def attributes_changed_by_setter
179
+ super.merge(metadata.try(:changed_metadata) || {})
180
+ end
181
+
182
+ # @private
183
+ def attribute_will_change!(attr)
184
+ if attribute_names.include?(attr) then
185
+ super attr
186
+ else
187
+ metadata!.send :attribute_will_change!, attr
188
+ end
175
189
  end
176
190
  end
177
191
  end
@@ -1,11 +1,14 @@
1
1
  # Stores information about a model that doesn't need to be in that model's
2
- # table. Each row in the @metadata@ table stores a schemaless, serialized hash
2
+ # table. Each row in the `metadata` table stores a schemaless, serialized hash
3
3
  # of data associated with a model instance. Any model can have an associated row
4
- # in the @metadata@ table by using the {HasMetadata} module.
4
+ # in the `metadata` table by using the {HasMetadata} module.
5
5
  #
6
- # h2. Properties
6
+ # Properties
7
+ # ----------
7
8
  #
8
- # | @data@ | A hash of this metadata's contents (YAML serialized in the database). |
9
+ # | | |
10
+ # |:-------|:----------------------------------------------------------------------|
11
+ # | `data` | A hash of this metadata's contents (YAML serialized in the database). |
9
12
 
10
13
  class Metadata < HasMetadata::Model
11
14
  end
metadata CHANGED
@@ -1,93 +1,112 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: has_metadata
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
5
- prerelease:
4
+ version: 1.6.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tim Morgan
9
- autorequire:
10
8
  bindir: bin
11
9
  cert_chain: []
12
- date: 2012-01-25 00:00:00.000000000 Z
10
+ date: 2013-12-08 00:00:00.000000000 Z
13
11
  dependencies:
14
12
  - !ruby/object:Gem::Dependency
15
13
  name: rails
16
- requirement: &70331322795420 !ruby/object:Gem::Requirement
17
- none: false
14
+ requirement: !ruby/object:Gem::Requirement
18
15
  requirements:
19
- - - ! '>='
16
+ - - ">="
20
17
  - !ruby/object:Gem::Version
21
18
  version: '3.2'
22
19
  type: :runtime
23
20
  prerelease: false
24
- version_requirements: *70331322795420
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '3.2'
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: boolean
27
- requirement: &70331322972780 !ruby/object:Gem::Requirement
28
- none: false
28
+ requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ! '>='
30
+ - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70331322972780
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
36
40
  - !ruby/object:Gem::Dependency
37
41
  name: jeweler
38
- requirement: &70331322983680 !ruby/object:Gem::Requirement
39
- none: false
42
+ requirement: !ruby/object:Gem::Requirement
40
43
  requirements:
41
- - - ! '>='
44
+ - - ">="
42
45
  - !ruby/object:Gem::Version
43
46
  version: '0'
44
47
  type: :development
45
48
  prerelease: false
46
- version_requirements: *70331322983680
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
47
54
  - !ruby/object:Gem::Dependency
48
55
  name: yard
49
- requirement: &70331322981100 !ruby/object:Gem::Requirement
50
- none: false
56
+ requirement: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - ! '>='
58
+ - - ">="
53
59
  - !ruby/object:Gem::Version
54
60
  version: '0'
55
61
  type: :development
56
62
  prerelease: false
57
- version_requirements: *70331322981100
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
58
68
  - !ruby/object:Gem::Dependency
59
69
  name: RedCloth
60
- requirement: &70331322991560 !ruby/object:Gem::Requirement
61
- none: false
70
+ requirement: !ruby/object:Gem::Requirement
62
71
  requirements:
63
- - - ! '>='
72
+ - - ">="
64
73
  - !ruby/object:Gem::Version
65
74
  version: '0'
66
75
  type: :development
67
76
  prerelease: false
68
- version_requirements: *70331322991560
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
69
82
  - !ruby/object:Gem::Dependency
70
83
  name: sqlite3
71
- requirement: &70331322997040 !ruby/object:Gem::Requirement
72
- none: false
84
+ requirement: !ruby/object:Gem::Requirement
73
85
  requirements:
74
- - - ! '>='
86
+ - - ">="
75
87
  - !ruby/object:Gem::Version
76
88
  version: '0'
77
89
  type: :development
78
90
  prerelease: false
79
- version_requirements: *70331322997040
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
80
96
  - !ruby/object:Gem::Dependency
81
97
  name: rspec
82
- requirement: &70331323012700 !ruby/object:Gem::Requirement
83
- none: false
98
+ requirement: !ruby/object:Gem::Requirement
84
99
  requirements:
85
- - - ! '>='
100
+ - - ">="
86
101
  - !ruby/object:Gem::Version
87
102
  version: '0'
88
103
  type: :development
89
104
  prerelease: false
90
- version_requirements: *70331323012700
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
91
110
  description: has_metadata lets you move non-indexed and weighty columns off of your
92
111
  big tables by creating a separate metadata table to store all this extra information.
93
112
  Works with Ruby 1.9. and Rails 3.0.
@@ -96,10 +115,10 @@ executables: []
96
115
  extensions: []
97
116
  extra_rdoc_files:
98
117
  - LICENSE
99
- - README.textile
118
+ - README.md
100
119
  files:
101
120
  - LICENSE
102
- - README.textile
121
+ - README.md
103
122
  - has_metadata.gemspec
104
123
  - lib/has_metadata.rb
105
124
  - lib/has_metadata/metadata_generator.rb
@@ -108,27 +127,32 @@ files:
108
127
  - templates/metadata.rb
109
128
  homepage: http://github.com/riscfuture/has_metadata
110
129
  licenses: []
111
- post_install_message:
130
+ metadata: {}
131
+ post_install_message: |2+
132
+
133
+ ⚠️ DEPRECATED: has_metadata is no longer maintained.
134
+
135
+ Superseded by `has_metadata_column` (also deprecated as of this notice). No active maintenance.
136
+
137
+ This is the final release. No further updates are planned.
138
+
112
139
  rdoc_options: []
113
140
  require_paths:
114
141
  - lib
115
142
  required_ruby_version: !ruby/object:Gem::Requirement
116
- none: false
117
143
  requirements:
118
- - - ! '>='
144
+ - - ">="
119
145
  - !ruby/object:Gem::Version
120
146
  version: '1.9'
121
147
  required_rubygems_version: !ruby/object:Gem::Requirement
122
- none: false
123
148
  requirements:
124
- - - ! '>='
149
+ - - ">="
125
150
  - !ruby/object:Gem::Version
126
151
  version: '0'
127
152
  requirements: []
128
- rubyforge_project:
129
- rubygems_version: 1.8.15
130
- signing_key:
131
- specification_version: 3
132
- summary: Reduce your table width by moving non-indexed columns to a separate metadata
133
- table
153
+ rubygems_version: 4.0.11
154
+ specification_version: 4
155
+ summary: "[DEPRECATED] Reduce your table width by moving non-indexed columns to a
156
+ separate metadata table"
134
157
  test_files: []
158
+ ...
data/README.textile DELETED
@@ -1,126 +0,0 @@
1
- h1. has_metadata -- Keep your tables narrow
2
-
3
- | *Author* | Tim Morgan |
4
- | *Version* | 1.6.1 (Jan 24, 2012) |
5
- | *License* | Released under the MIT License. |
6
-
7
- h2. Important note for those upgrading from 1.0 to 1.1
8
-
9
- You must re-run the @rails generate metadata@ task to update your @Metadata@
10
- model. When finished, your @app/models/metadata.rb@ file should look like:
11
-
12
- <pre><code>
13
- # Stores information about a model that doesn't need to be in that model's
14
- # table. Each row in the @metadata@ table stores a schemaless, serialized hash
15
- # of data associated with a model instance. Any model can have an associated row
16
- # in the @metadata@ table by using the {HasMetadata} module.
17
- #
18
- # h2. Properties
19
- #
20
- # | @data@ | A hash of this metadata's contents (YAML serialized in the database). |
21
-
22
- class Metadata &lt; HasMetadata::Model
23
- end
24
- </code></pre>
25
-
26
- Note that this is significantly emptier than the previous model.
27
-
28
- h2. About
29
-
30
- Wide tables are a problem for big databases. If your @ActiveRecord@ models have
31
- 10, maybe 15 columns, some of which are @VARCHARs@ or maybe even @TEXTs@, it's
32
- going to slow your queries down when you start to scale up.
33
-
34
- The easy solution to this problem is to limit your projections; in other words,
35
- to only @SELECT@ the columns that you actually need. If you've got a @users@
36
- table with a giant @about_me@ text column, and you're only trying to look up the
37
- user's login, then just select the @login@ column.
38
-
39
- In the long run, though, a superior solution is to just move those
40
- @about_me@-type columns to a completely different table. This table has just one
41
- JSON-serialized field, making it schemaless, so it doesn't waste space. Each row
42
- in this table is associated with a record in another table (@Metadata@ @has_one@
43
- of your models).
44
-
45
- This way, when your website gets huge, all of your giant, freeform data is in
46
- one table that you can shard, or move off to an alternate database, or even a
47
- NoSQL-type document store, or otherwise manage as you please. Your relational
48
- tables remain slim and efficient, containing only columns that a) are indexed,
49
- or b) you need frequent access to.
50
-
51
- This gem includes a generator that creates the @Metadata@ model, and a module
52
- that you can include in your models to define which fields have been spun off to
53
- the metadata record.
54
-
55
- h2. Installation
56
-
57
- *Important Note:* This gem is only compatible with Ruby 1.9 and Rails 3.0.
58
-
59
- Firstly, add the gem to your Rails project's @Gemfile@:
60
-
61
- <pre><code>
62
- gem 'has_metadata'
63
- </code></pre>
64
-
65
- Next, run the generator, which will add the @Metadata@ model and its migration
66
- to your application.
67
-
68
- <pre><code>
69
- rails generate metadata
70
- </code></pre>
71
-
72
- h2. Usage
73
-
74
- The first thing to think about is what columns to keep in your model. You will
75
- need to keep any indexed columns, or any columns you perform lookups or other
76
- SQL queries with. You should also keep any frequently accessed columns,
77
- especially if they are small (integers or booleans). Good candidates for the
78
- metadata table are the @TEXT@- and @VARCHAR@-type columns that you only need to
79
- render a page or two in your app.
80
-
81
- You'll need to change your model's schema so that it has a @metadata_id@ column
82
- that will associate the model with its @Metadata@ instance:
83
-
84
- <pre><code>
85
- t.belongs_to :metadata
86
- </code></pre>
87
-
88
- Next, include the @HasMetadata@ module in your model, and call the
89
- @has_metadata@ method to define the schema of your metadata. You can get more
90
- information in the {HasMetadata::ClassMethods#has_metadata} documentation, but for starters, here's a
91
- basic example:
92
-
93
- <pre><code>
94
- class User < ActiveRecord::Base
95
- include HasMetadata
96
- has_metadata({
97
- about_me: { type: String, length: { maximum: 512 } },
98
- birthdate: { type: Date, presence: true },
99
- zipcode: { type: Number, numericality: { greater_than: 9999, less_than: 10_000_} }
100
- })
101
- end
102
- </code></pre>
103
-
104
- As you can see, you pass field names mapped to a hash. The hash describes the
105
- validation that will be performed, and is in the same format as a call to
106
- @validates@. In addition to the @EachValidator@ keys shown above, you can also
107
- pass a @type@ key, to constrain the Ruby type that can be assigned to the field.
108
-
109
- Each of these fields (in this case, @about_me@, @birthdate@, and @zipcode@) can
110
- be accessed and set as first_level methods on an instance of your model:
111
-
112
- <pre><code>
113
- user.about_me #=> "I was born in 1982 in Aberdeen. My father was a carpenter from..."
114
- </code></pre>
115
-
116
- ... and thus, used as part of @form_for@ fields:
117
-
118
- <pre><code>
119
- form_for user do |f|
120
- f.text_area :about_me, rows: 5, cols: 80
121
- end
122
- </code></pre>
123
-
124
- The only thing you _can't_ do is use these fields in a query, obviously. You
125
- can't do something like @User.where(zipcode: 90210)@, because that column
126
- doesn't exist on the @users@ table.