schemattr 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3162b47b2a1acf700ca81a8ee47222391cf0711ad4b5194b9d5c46cf19584162
4
- data.tar.gz: 12b294d20e189e9d16bb23644a26199829bccd3c42ba1b7662aea33b79ae4662
3
+ metadata.gz: 4d2d2b02fcfc5238afd51f0741a619f334315e785b91c2add642cc1ef0955962
4
+ data.tar.gz: b586cd63d36d773027f6786b81c785eba67b4439a1f9999140e7bff4ad44eb4d
5
5
  SHA512:
6
- metadata.gz: 1134ffee2611f6f203f3891fe21088121a80f7ceb6a02197dd8cf4aa97b114d575a82c6652217faafb840ecbf6dbf904d61169984ee3cf7fb499dcb035f1a2fe
7
- data.tar.gz: dee2aa5f9b8120885f8a0422de822e5ced1bf60103668149963d8ce8866c535db0915123427968af0b3b85653fb18626540190bad2ca16120da5bd79c7385c26
6
+ metadata.gz: 6bd7afaa4e360c1efe3b171fe2815f2687c23aaf6f1243bdb162ad720788ffd531b2569bfc63e16cd35698a0ad52fdc80196518703651c02d4e7251fe985a59c
7
+ data.tar.gz: a59b2bd4c1f0bc29ba27d0859512fd863208f4b7591d4a951e67b60e2f80c4a6053fbd61b0598ef264798249ae84c3df4d51591ff9c18f24cc88ec23daee7bb3
@@ -1,6 +1,6 @@
1
- Copyright 2015 Jeremy Jackson / ModeSet
1
+ Copyright 2019 Jeremy Jackson
2
2
 
3
- https://github.com/modeset/schemattr
3
+ https://github.com/jejacks0n/schemattr
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -2,17 +2,15 @@ Schemattr
2
2
  =========
3
3
 
4
4
  [![Gem Version](https://img.shields.io/gem/v/schemattr.svg)](http://badge.fury.io/rb/schemattr)
5
- [![Build Status](https://img.shields.io/travis/modeset/schemattr.svg)](https://travis-ci.org/modeset/schemattr)
6
- [![Code Climate](https://codeclimate.com/github/modeset/schemattr/badges/gpa.svg)](https://codeclimate.com/github/modeset/schemattr)
7
- [![Test Coverage](https://codeclimate.com/github/modeset/schemattr/badges/coverage.svg)](https://codeclimate.com/github/modeset/schemattr)
8
- [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
9
- [![Dependency Status](https://gemnasium.com/modeset/schemattr.svg)](https://gemnasium.com/modeset/schemattr)
5
+ [![Build Status](https://img.shields.io/travis/jejacks0n/schemattr.svg)](https://travis-ci.org/jejacks0n/schemattr)
6
+ [![Code Climate](https://codeclimate.com/github/jejacks0n/schemattr/badges/gpa.svg)](https://codeclimate.com/github/jejacks0n/schemattr)
7
+ [![Test Coverage](https://codeclimate.com/github/jejacks0n/schemattr/badges/coverage.svg)](https://codeclimate.com/github/jejacks0n/schemattr)
8
+ [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
10
9
 
11
10
  Schemattr is an ActiveRecord extension that provides a helpful schema-less attribute DSL. It can be used to define a
12
11
  simple schema for a single attribute that can change over time without having to migrate existing data.
13
12
 
14
13
  ### Background
15
-
16
14
  Let's say you have a User model, and that model has a simple concept of settings -- just one for now. It's a boolean
17
15
  named `opted_in`, and it means that the user is opted in to receive email updates. Sweet, we go add a migration for this
18
16
  setting and migrate. Ship it, we're done with that feature.
@@ -34,39 +32,12 @@ methods, can keep a real column synced with one if its fields, and more.
34
32
  If you're using Schemattr and want to add a new setting field, it's as simple as adding a new field to the attribute
35
33
  schema and setting a default right there in the code. No migrations, no hassles, easy deployment.
36
34
 
37
-
38
- ## Table of Contents
39
-
40
- 1. [Installation](#installation)
41
- 2. [Usage](#usage)
42
- - [Field types](#field-types)
43
- - [Delegating](#delegating)
44
- - [Strict mode](#strict-mode-vs-arbitrary-fields)
45
- - [Overriding](#overriding-functionality)
46
- - [Renaming fields](#renaming-fields)
47
- - [Syncing attributes](#syncing-attributes)
48
-
49
-
50
35
  ## Installation
51
-
52
- Add it to your Gemfile:
53
36
  ```ruby
54
- gem 'schemattr'
55
- ```
56
-
57
- And then execute:
58
- ```shell
59
- $ bundle
60
- ```
61
-
62
- Or install it yourself as:
63
- ```shell
64
- $ gem install schemattr
37
+ gem "schemattr"
65
38
  ```
66
39
 
67
-
68
40
  ## Usage
69
-
70
41
  In the examples we assume there's already a User model and table.
71
42
 
72
43
  First, let's create a migration to add your schema-less attribute. In postgres you can use a JSON column. We use the
@@ -113,7 +84,6 @@ when they're persisted they'll include whatever we've changed them to be. If we
113
84
  they'll just be the defaults if we ever ask again.
114
85
 
115
86
  ### Field types
116
-
117
87
  The various field types are outlined below. When you define a string field for instance, the value will be coerced into
118
88
  a string at the time that it's set.
119
89
 
@@ -135,14 +105,13 @@ field is set -- this is intended for when you need something that doesn't care w
135
105
  harder to use in forms however.
136
106
 
137
107
  ### Delegating
138
-
139
108
  If you don't like the idea of having to access these attributes at `user.settings` you can specify that you'd like them
140
109
  delegated. This adds delegation of the methods that exist on settings to the User instances.
141
110
 
142
111
  ```ruby
143
- attribute_schema :settings, delegated: true do
144
- field :opted_in, :boolean, default: true
145
- end
112
+ attribute_schema :settings, delegated: true do
113
+ field :opted_in, :boolean, default: true
114
+ end
146
115
  ```
147
116
 
148
117
  ```ruby
@@ -153,7 +122,6 @@ user.opted_in? # => false
153
122
  ```
154
123
 
155
124
  ### Strict mode vs. arbitrary fields
156
-
157
125
  By default, Schemattr doesn't allow arbitrary fields to be added, but it supports it. When strict mode is disabled, it
158
126
  allows any arbitrary field to be set or asked for.
159
127
 
@@ -161,9 +129,9 @@ allows any arbitrary field to be set or asked for.
161
129
  access them through the attribute that you've defined -- in our case, it's `settings`.
162
130
 
163
131
  ```ruby
164
- attribute_schema :settings, delegated: true, strict: false do
165
- field :opted_in, :boolean, default: true
166
- end
132
+ attribute_schema :settings, delegated: true, strict: false do
133
+ field :opted_in, :boolean, default: true
134
+ end
167
135
  ```
168
136
 
169
137
  ```ruby
@@ -175,7 +143,6 @@ user.foo # => NoMethodError
175
143
  ```
176
144
 
177
145
  ### Overriding
178
-
179
146
  Schemattr provides the ability to specify your own attribute class. By doing so you can provide your own getters and
180
147
  setters and do more complex logic. In this example we're providing the inverse of `opted_in` with an `opted_out` psuedo
181
148
  field.
@@ -188,15 +155,15 @@ class UserSettings < Schemattr::Attribute
188
155
  alias_method :opted_out, :opted_out?
189
156
 
190
157
  def opted_out=(val)
191
- opted_in = !val
158
+ self.opted_in = !val
192
159
  end
193
160
  end
194
161
  ```
195
162
 
196
163
  ```ruby
197
- attribute_schema :settings, class: UserSettings do
198
- field :opted_in, :boolean, default: true
199
- end
164
+ attribute_schema :settings, class: UserSettings do
165
+ field :opted_in, :boolean, default: true
166
+ end
200
167
  ```
201
168
 
202
169
  ```ruby
@@ -211,7 +178,6 @@ Our custom `opted_out` psuedo field won't be persisted, because it's not a defin
211
178
  existing field that is persisted (`opted_in`).
212
179
 
213
180
  #### Getters and setters
214
-
215
181
  When overriding the attribute class with your own, you can provide your own custom getters and setters as well. These
216
182
  will not be overridden by whatever Schemattr thinks they should do. Take this example, where when someone turns on or
217
183
  off a setting we want to subscribe/unsubscribe them to an email list via a third party.
@@ -233,17 +199,16 @@ end
233
199
  *Note*: This is not a real world scenario but serves our purposes of describing an example.
234
200
 
235
201
  ### Renaming fields
236
-
237
202
  Schemattr makes it easy to rename fields as well. Let's say you've got a field named `opted_in`, as the examples have
238
203
  shown thus far. But you've added new email lists, and you think `opted_in` is too vague. Like, opted in for what?
239
204
 
240
205
  We can create a new field that is correctly named, and specify what attribute we want to pull the value from.
241
206
 
242
207
  ```ruby
243
- attribute_schema :settings do
244
- # field :opted_in, :boolean, default: true
245
- field :email_list_beginner, :boolean, from: :opted_in, default: true
246
- end
208
+ attribute_schema :settings do
209
+ # field :opted_in, :boolean, default: true
210
+ field :email_list_beginner, :boolean, from: :opted_in, default: true
211
+ end
247
212
  ```
248
213
 
249
214
  Specifying the `from: :opted_in` option will tell Schemattr to look for the value that may have already been defined in
@@ -260,9 +225,9 @@ Let's say we want to be able to be able to easily query users who have opted in.
260
225
  leave it, as the case may be) on the users table.
261
226
 
262
227
  ```ruby
263
- attribute_schema :settings do
264
- field :email_list_beginner, :boolean, default: true, sync: :opted_in
265
- end
228
+ attribute_schema :settings do
229
+ field :email_list_beginner, :boolean, default: true, sync: :opted_in
230
+ end
266
231
  ```
267
232
 
268
233
  ```ruby
@@ -281,9 +246,7 @@ things in sync easier. The second issue can arise is when this attribute is set
281
246
  using things like `user.update_column(:opted_in, false)`, and `User.update_all(opted_in: false)` will allow things to
282
247
  get out of sync.
283
248
 
284
-
285
249
  ## Querying a JSON column
286
-
287
250
  This has come up a little bit, and so it's worth documenting -- though it has very little to do with Schemattr. When you
288
251
  have a JSON column in postgres, you can query values from within that column in various ways.
289
252
 
@@ -295,13 +258,9 @@ User.where("(settings->>'opted_in')::boolean") # boolean query
295
258
  User.where("settings->>'string_value' = ?", "some string") # string query
296
259
  ```
297
260
 
298
-
299
261
  ## License
262
+ Licensed under the [MIT License](http://creativecommons.org/licenses/MIT/)
300
263
 
301
- Licensed under the [MIT License](http://creativecommons.org/licenses/MIT)
302
-
303
- Copyright 2015 [Mode Set](https://github.com/modeset)
304
-
264
+ Copyright 2019 [jejacks0n](https://github.com/jejacks0n)
305
265
 
306
266
  ## Make Code Not War
307
- ![crest](https://secure.gravatar.com/avatar/aa8ea677b07f626479fd280049b0e19f?s=75)
@@ -23,7 +23,7 @@ module Schemattr
23
23
  end
24
24
 
25
25
  define_method "#{name}" do
26
- _schemaless_attributes[name] ||= attribute_schema.attribute_class.new(self, name, options[:strict] == false)
26
+ schemaless_attributes[name] ||= attribute_schema.attribute_class.new(self, name, options[:strict] == false)
27
27
  end
28
28
  end
29
29
  end
@@ -33,14 +33,14 @@ module Schemattr
33
33
  end
34
34
 
35
35
  def reload(*_args)
36
- _schemaless_attributes.keys.each { |name| _schemaless_attributes[name] = nil }
36
+ schemaless_attributes.keys.each { |name| schemaless_attributes[name] = nil }
37
37
  super
38
38
  end
39
39
 
40
40
  private
41
41
 
42
- def _schemaless_attributes
43
- @_schemaless_attributes ||= {}
44
- end
42
+ def schemaless_attributes
43
+ @_schemaless_attributes ||= {}
44
+ end
45
45
  end
46
46
  end
@@ -23,38 +23,38 @@ module Schemattr
23
23
 
24
24
  private
25
25
 
26
- def method_missing(m, *args)
27
- if @allow_arbitrary_attributes
28
- self[$1] = args[0] if args.length == 1 && /^(\w+)=$/ =~ m
29
- self[m.to_s.gsub(/\?$/, "")]
30
- else
31
- raise NoMethodError, "undefined method '#{m}' for #{self.class}"
26
+ def method_missing(m, *args)
27
+ if @allow_arbitrary_attributes
28
+ self[$1] = args[0] if args.length == 1 && /^(\w+)=$/ =~ m
29
+ self[m.to_s.gsub(/\?$/, "")]
30
+ else
31
+ raise NoMethodError, "undefined method '#{m}' for #{self.class}"
32
+ end
32
33
  end
33
- end
34
34
 
35
- def migrate_value(val, from)
36
- return val unless from
37
- if (old_val = self[from]).nil?
38
- val
39
- else
40
- @hash.delete(from.to_s)
41
- old_val
35
+ def migrate_value(val, from)
36
+ return val unless from
37
+ if (old_val = self[from]).nil?
38
+ val
39
+ else
40
+ @hash.delete(from.to_s)
41
+ old_val
42
+ end
42
43
  end
43
- end
44
44
 
45
- def sync_value(val, to)
46
- model[to] = val if to
47
- val
48
- end
45
+ def sync_value(val, to)
46
+ model[to] = val if to
47
+ val
48
+ end
49
49
 
50
- def []=(key, val)
51
- hash[key.to_s] = val
52
- model[attr_name] = hash
53
- val
54
- end
50
+ def []=(key, val)
51
+ hash[key.to_s] = val
52
+ model[attr_name] = hash
53
+ val
54
+ end
55
55
 
56
- def [](key)
57
- hash[key.to_s]
58
- end
56
+ def [](key)
57
+ hash[key.to_s]
58
+ end
59
59
  end
60
60
  end
@@ -14,73 +14,71 @@ module Schemattr
14
14
 
15
15
  protected
16
16
 
17
- def field(name, type, options = {})
18
- if respond_to?(type, true)
19
- send(type, name, options)
20
- else
21
- _define(name, false, options)
17
+ def field(name, type, options = {})
18
+ if respond_to?(type, true)
19
+ send(type, name, options)
20
+ else
21
+ define(name, false, options)
22
+ end
22
23
  end
23
- end
24
24
 
25
- def string(name, options = {})
26
- _define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_s, options[:sync]) }
27
- end
25
+ def string(name, options = {})
26
+ define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_s, options[:sync]) }
27
+ end
28
28
 
29
- def integer(name, options = {})
30
- _define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_i, options[:sync]) }
31
- end
29
+ def integer(name, options = {})
30
+ define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_i, options[:sync]) }
31
+ end
32
32
 
33
- def float(name, options = {})
34
- _define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_f, options[:sync]) }
35
- end
33
+ def float(name, options = {})
34
+ define name, false, options, setter: lambda { |val| sync_value(self[name] = val.to_f, options[:sync]) }
35
+ end
36
36
 
37
- def datetime(name, options = {})
38
- _define name, false, options
39
- end
37
+ def datetime(name, options = {})
38
+ define name, false, options
39
+ end
40
40
 
41
- def date(name, options = {})
42
- _define name, false, options
43
- end
41
+ def date(name, options = {})
42
+ define name, false, options
43
+ end
44
44
 
45
- def boolean(name, options = {})
46
- _define name, true, options, setter: lambda { |val|
47
- bool = ActiveRecord::Type::Boolean.new.deserialize(val)
48
- sync_value(self[name] = bool, options[:sync])
49
- }
50
- end
45
+ def boolean(name, options = {})
46
+ define name, true, options, setter: lambda { |val|
47
+ bool = ActiveRecord::Type::Boolean.new.deserialize(val)
48
+ sync_value(self[name] = bool, options[:sync])
49
+ }
50
+ end
51
51
 
52
- alias_method :text, :string
53
- alias_method :bigint, :integer
54
- alias_method :decimal, :float
55
- alias_method :time, :datetime
52
+ alias_method :text, :string
53
+ alias_method :bigint, :integer
54
+ alias_method :decimal, :float
55
+ alias_method :time, :datetime
56
56
 
57
57
  private
58
58
 
59
- def _define(name, boolean, options, blocks = {})
60
- setter = blocks[:setter] || lambda { sync_value(self[name] = val, options[:sync]) }
61
- getter = blocks[:getter] || lambda { migrate_value(self[name], options[:from]) }
62
- _default(name, options[:default])
63
- _method("#{name}=", options[:sync], &setter)
64
- _method(name, options[:sync], &getter)
65
- _alias("#{name}?", name, options[:sync]) if boolean
66
- end
59
+ def define(name, boolean, options, blocks = {})
60
+ setter = blocks[:setter] || lambda { sync_value(self[name] = val, options[:sync]) }
61
+ getter = blocks[:getter] || lambda { migrate_value(self[name], options[:from]) }
62
+ default_for(name, options[:default])
63
+ method_for("#{name}=", options[:sync], &setter)
64
+ method_for(name, options[:sync], &getter)
65
+ alias_for("#{name}?", name, options[:sync]) if boolean
66
+ end
67
67
 
68
- def _default(name, default)
69
- @defaults[name.to_s] = default
70
- end
68
+ def default_for(name, default)
69
+ @defaults[name.to_s] = default
70
+ end
71
71
 
72
- def _method(name, delegated = false, &block)
73
- @delegated.push(name.to_s) if delegated
74
- unless attribute_class.instance_methods.include?(name.to_sym)
75
- attribute_class.send(:define_method, name, &block)
72
+ def method_for(name, delegated = false, &block)
73
+ @delegated.push(name.to_s) if delegated
74
+ unless attribute_class.instance_methods.include?(name.to_sym)
75
+ attribute_class.send(:define_method, name, &block)
76
+ end
76
77
  end
77
- end
78
78
 
79
- def _alias(new, old, delegated)
80
- @delegated.push(new.to_s) if delegated
81
- unless attribute_class.instance_methods.include?(new.to_sym)
82
- attribute_class.send(:alias_method, new, old)
79
+ def alias_for(new, old, delegated)
80
+ @delegated.push(new.to_s) if delegated
81
+ attribute_class.send(:alias_method, new, old) unless attribute_class.instance_methods.include?(new.to_sym)
83
82
  end
84
- end
85
83
  end
86
84
  end
@@ -1,3 +1,3 @@
1
1
  module Schemattr
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,18 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schemattr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - jejacks0n
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-16 00:00:00.000000000 Z
11
+ date: 2019-04-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: ''
13
+ description: Write schema-less attributes in ActiveRecord using a helpful and flexible
14
+ DSL.
14
15
  email:
15
- - info@modeset.com
16
+ - jejacks0n@gmail.com
16
17
  executables: []
17
18
  extensions: []
18
19
  extra_rdoc_files: []
@@ -24,7 +25,7 @@ files:
24
25
  - lib/schemattr/attribute.rb
25
26
  - lib/schemattr/dsl.rb
26
27
  - lib/schemattr/version.rb
27
- homepage: https://github.com/modeset/schemattr
28
+ homepage: http://github.com/jejacks0n/bitbot
28
29
  licenses:
29
30
  - MIT
30
31
  metadata: {}
@@ -34,9 +35,9 @@ require_paths:
34
35
  - lib
35
36
  required_ruby_version: !ruby/object:Gem::Requirement
36
37
  requirements:
37
- - - ">="
38
+ - - "~>"
38
39
  - !ruby/object:Gem::Version
39
- version: '0'
40
+ version: '2.4'
40
41
  required_rubygems_version: !ruby/object:Gem::Requirement
41
42
  requirements:
42
43
  - - ">="
@@ -47,5 +48,5 @@ rubyforge_project:
47
48
  rubygems_version: 2.7.6
48
49
  signing_key:
49
50
  specification_version: 4
50
- summary: ''
51
+ summary: 'Schemattr: Simple schema-less column definitions for ActiveRecord'
51
52
  test_files: []