store_schema 0.0.1
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 +7 -0
- data/.gemfiles/4.0.gemfile +3 -0
- data/.gemfiles/4.1.gemfile +3 -0
- data/.gemfiles/4.2.gemfile +3 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +157 -0
- data/Rakefile +4 -0
- data/lib/store_schema/accessor_definer.rb +89 -0
- data/lib/store_schema/configuration.rb +66 -0
- data/lib/store_schema/converter/base.rb +12 -0
- data/lib/store_schema/converter/boolean.rb +49 -0
- data/lib/store_schema/converter/date_time.rb +38 -0
- data/lib/store_schema/converter/float.rb +34 -0
- data/lib/store_schema/converter/integer.rb +32 -0
- data/lib/store_schema/converter/string.rb +25 -0
- data/lib/store_schema/converter.rb +50 -0
- data/lib/store_schema/module.rb +36 -0
- data/lib/store_schema/version.rb +3 -0
- data/lib/store_schema.rb +11 -0
- data/spec/lib/casted_store_accessor_spec.rb +172 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/db.rb +17 -0
- data/spec/support/env.rb +14 -0
- data/spec/support/models.rb +12 -0
- data/store_schema.gemspec +29 -0
- metadata +218 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d13d481527cfe8e42df69d8c0ac8277a09d0b2f7
|
4
|
+
data.tar.gz: 4bfba69ec1c4ce763a544aa8eb1cdd3ec7aad8eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 870cf0a943b7c6c27c8a11eb961b65ae05033471f76d755391baf1a7e8f88be8bd959c3b7d3a4faa0c3c323ef91119909414e5ef5099d08b8b463d6f5968a0d8
|
7
|
+
data.tar.gz: b8db099f6f49b350e53aa39483d7200db482b40f3deacab9b1151fff93ed9d5132de10d22e3f0e81122ae90ebe3f4202103851674ad9c9c12954637a0466d859
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
.DS_Store
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Michael van Rooijen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
# StoreSchema
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/meskyanichi/store_schema)
|
4
|
+
[](https://travis-ci.org/meskyanichi/store_schema)
|
5
|
+
|
6
|
+
StoreSchema, for Rails/ActiveRecord 4.0.0+, enhances `ActiveRecord::Base.store_accessor` with data conversion capabilities.
|
7
|
+
|
8
|
+
This library was developed for- and extracted from [HireFire].
|
9
|
+
|
10
|
+
|
11
|
+
### Compatibility
|
12
|
+
|
13
|
+
- Rails/ActiveRecord 4.0.0+
|
14
|
+
- Ruby (MRI) 2.0+
|
15
|
+
- Ruby (RBX) 2.2+
|
16
|
+
|
17
|
+
|
18
|
+
### Installation
|
19
|
+
|
20
|
+
Distributed at a gem, hosted at [RubyGems.org].
|
21
|
+
|
22
|
+
```rb
|
23
|
+
gem "store_schema"
|
24
|
+
```
|
25
|
+
|
26
|
+
|
27
|
+
### Example
|
28
|
+
|
29
|
+
This example assumes you have a `websites` table with a column named
|
30
|
+
`config` of type `text`.
|
31
|
+
|
32
|
+
Define a model and use `store_schema`.
|
33
|
+
|
34
|
+
```rb
|
35
|
+
class Website < ActiveRecord::Base
|
36
|
+
|
37
|
+
# Tell ActiveRecord that we want to serialize the :config attribute
|
38
|
+
# and store the serialized data as text in the config column.
|
39
|
+
#
|
40
|
+
# If you're using PostreSQL's "hstore" column-type instead of the
|
41
|
+
# "text" column-type, you don't have to define `serialize :config`.
|
42
|
+
#
|
43
|
+
serialize :config
|
44
|
+
|
45
|
+
# Define a schema for the store. This syntax is similar to
|
46
|
+
# ActiveRecord::Migration.
|
47
|
+
#
|
48
|
+
store_schema :config do |s|
|
49
|
+
s.string :name
|
50
|
+
s.integer :visitors
|
51
|
+
s.float :apdex
|
52
|
+
s.boolean :ssl
|
53
|
+
s.datetime :published_at
|
54
|
+
end
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
Now you can get and set attributes on the `websites.config` column using
|
59
|
+
the generated accessors.
|
60
|
+
|
61
|
+
```rb
|
62
|
+
website = Website.create(
|
63
|
+
name: "Example Website",
|
64
|
+
visitors: 1337,
|
65
|
+
apdex: 1.0,
|
66
|
+
ssl: true,
|
67
|
+
published_at: Time.now
|
68
|
+
)
|
69
|
+
|
70
|
+
p website.name # => "Example Website" (String)
|
71
|
+
p website.visitors # => 1337 (Fixnum)
|
72
|
+
p website.apdex # => 1.0 (Float)
|
73
|
+
p website.ssl # => true (TrueClass)
|
74
|
+
p website.published_at # => "Thu, 18 Sep 2014 23:18:11 +0000" (DateTime)
|
75
|
+
|
76
|
+
p website.config
|
77
|
+
# =>
|
78
|
+
# {
|
79
|
+
# "name" => "Example Website",
|
80
|
+
# "visitors" => "1337",
|
81
|
+
# "apdex" => "1.0",
|
82
|
+
# "ssl" => "t",
|
83
|
+
# "published_at" => "2014-09-18 23:18:11.583168000"
|
84
|
+
# }
|
85
|
+
```
|
86
|
+
|
87
|
+
That's it. This is similar to just using `store_accessor`, except that
|
88
|
+
`store_schema` is more strict as to what data types are stored. It attempts
|
89
|
+
to stay consistent with ActiveRecord's column conventions such as storing
|
90
|
+
booleans (`0`, `"0"`, `1`, `"1"`, `"t"`, `"T"`, `"f"`, `"F"`, `true`,
|
91
|
+
`"true"`, `"TRUE"`, `false`, `"false"`, `"FALSE"`, `"on"`, `"ON"`, `"off"`,
|
92
|
+
`"OFF"`) as `"t"` and `"f"`, storing `Time`, `Date` as `DateTime`,
|
93
|
+
ensuring `Time` is UTC prior to being stored, and more.
|
94
|
+
|
95
|
+
When accessing stored data, it properly converts them to their data types.
|
96
|
+
For example, `"t"` is converted to a TrueClass, and
|
97
|
+
`"2014-09-18 23:18:11.583168000"` is converted back to a DateTime.
|
98
|
+
See above example.
|
99
|
+
|
100
|
+
If you need to be able to query these serialized attributes,
|
101
|
+
consider using [PostgreSQL's HStore Extension]. If you do not need to
|
102
|
+
be able to query the serialized data, you can simply use a text-type column
|
103
|
+
and use the `serialize` method in your model which works with any SQL database.
|
104
|
+
|
105
|
+
|
106
|
+
### Contributing
|
107
|
+
|
108
|
+
Contributions are welcome, but please conform to these requirements:
|
109
|
+
|
110
|
+
- Ruby (MRI) 2.0+
|
111
|
+
- Ruby (RBX) 2.2+
|
112
|
+
- ActiveRecord 4.0.0+
|
113
|
+
- 100% Spec Coverage
|
114
|
+
- Generated by when running the test suite
|
115
|
+
- 100% [Passing Specs]
|
116
|
+
- Run test suite with `$ rspec spec`
|
117
|
+
- 4.0 [Code Climate Score]
|
118
|
+
- Run `$ rubycritic lib` to generate the score locally and receive tips
|
119
|
+
- No code smells
|
120
|
+
- No duplication
|
121
|
+
|
122
|
+
To start contributing, fork the project, clone it, and install the development dependencies:
|
123
|
+
|
124
|
+
```
|
125
|
+
git clone git@github.com:USERNAME/store_schema.git
|
126
|
+
cd store_schema
|
127
|
+
bundle
|
128
|
+
```
|
129
|
+
|
130
|
+
Ensure that everything works:
|
131
|
+
|
132
|
+
```
|
133
|
+
rspec spec
|
134
|
+
rubycritic lib
|
135
|
+
```
|
136
|
+
|
137
|
+
Create a new branch and start hacking:
|
138
|
+
|
139
|
+
```
|
140
|
+
git checkout -b my-contributions
|
141
|
+
```
|
142
|
+
|
143
|
+
Submit a pull request.
|
144
|
+
|
145
|
+
|
146
|
+
### Author / License
|
147
|
+
|
148
|
+
Copyright (c) 2014 Michael van Rooijen ( [@meskyanichi] )<br />
|
149
|
+
Released under the MIT [License].
|
150
|
+
|
151
|
+
[@meskyanichi]: https://twitter.com/meskyanichi
|
152
|
+
[HireFire]: http://hirefire.io
|
153
|
+
[Passing Specs]: https://travis-ci.org/meskyanichi/store_schema
|
154
|
+
[Code Climate Score]: https://codeclimate.com/github/meskyanichi/store_schema
|
155
|
+
[License]: https://github.com/meskyanichi/store_schema/blob/master/LICENSE
|
156
|
+
[RubyGems.org]: https://rubygems.org/gems/store_schema
|
157
|
+
[PostgreSQL's HStore Extension]: http://www.postgresql.org/docs/9.3/static/hstore.html
|
data/Rakefile
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
class StoreSchema::AccessorDefiner
|
2
|
+
class InvalidValueType < StandardError; end
|
3
|
+
|
4
|
+
# @return [Class]
|
5
|
+
#
|
6
|
+
attr_reader :klass
|
7
|
+
|
8
|
+
# @return [Symbol]
|
9
|
+
#
|
10
|
+
attr_reader :column
|
11
|
+
|
12
|
+
# @return [Symbol]
|
13
|
+
#
|
14
|
+
attr_reader :type
|
15
|
+
|
16
|
+
# @return [Symbol]
|
17
|
+
#
|
18
|
+
attr_reader :attribute
|
19
|
+
|
20
|
+
# @param klass [Class] the class to define the accessor on
|
21
|
+
# @param column [Symbol] the name of the column to define the accessor on
|
22
|
+
# @param type [Symbol] the data type of the {#attribute}
|
23
|
+
# @param attribute [Symbol] the name of the {#column}'s attribute
|
24
|
+
#
|
25
|
+
def initialize(klass, column, type, attribute)
|
26
|
+
@klass = klass
|
27
|
+
@column = column
|
28
|
+
@type = type
|
29
|
+
@attribute = attribute
|
30
|
+
end
|
31
|
+
|
32
|
+
# Defines all necessary accessors on {#klass}.
|
33
|
+
#
|
34
|
+
def define
|
35
|
+
define_store_accessor
|
36
|
+
define_getter
|
37
|
+
define_setter
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Defines the standard store accessor.
|
43
|
+
#
|
44
|
+
def define_store_accessor
|
45
|
+
klass.store_accessor(column, attribute)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Enhances the store getter by adding data conversion capabilities.
|
49
|
+
#
|
50
|
+
def define_getter
|
51
|
+
_type = type
|
52
|
+
|
53
|
+
klass.send(:define_method, attribute) do
|
54
|
+
value = super()
|
55
|
+
|
56
|
+
if value.is_a?(NilClass)
|
57
|
+
value
|
58
|
+
else
|
59
|
+
StoreSchema::Converter.new(value, _type).from_db
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Enhances the store setter by adding data conversion capabilities.
|
65
|
+
#
|
66
|
+
def define_setter
|
67
|
+
_klass = klass
|
68
|
+
_column = column
|
69
|
+
_type = type
|
70
|
+
_attribute = attribute
|
71
|
+
|
72
|
+
klass.send(:define_method, "#{attribute}=") do |value|
|
73
|
+
if value.is_a?(NilClass)
|
74
|
+
super(value)
|
75
|
+
else
|
76
|
+
converted_value = StoreSchema::Converter
|
77
|
+
.new(value, _type).to_db
|
78
|
+
|
79
|
+
if converted_value
|
80
|
+
super(converted_value)
|
81
|
+
else
|
82
|
+
raise InvalidValueType,
|
83
|
+
"#{value} (#{value.class}) for " +
|
84
|
+
"#{_klass}##{_column}.#{_attribute} (#{_type})"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class StoreSchema::Configuration
|
2
|
+
|
3
|
+
# @return [Symbol]
|
4
|
+
#
|
5
|
+
attr_reader :column
|
6
|
+
|
7
|
+
# @return [Hash]
|
8
|
+
#
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
# @param column [Symbol] the table column to generate the accessors for
|
12
|
+
#
|
13
|
+
def initialize(column)
|
14
|
+
@column = column
|
15
|
+
@attributes = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param attribute [Symbol] the name of the attribute on {#column}
|
19
|
+
# for which to generate a String-type accessor
|
20
|
+
#
|
21
|
+
def string(attribute)
|
22
|
+
attributes[attribute] = :string
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param attribute [Symbol] the name of the attribute on {#column}
|
26
|
+
# for which to generate an Integer-type accessor
|
27
|
+
#
|
28
|
+
def integer(attribute)
|
29
|
+
attributes[attribute] = :integer
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param attribute [Symbol] the name of the attribute on {#column}
|
33
|
+
# for which to generate a Float-type accessor
|
34
|
+
#
|
35
|
+
def float(attribute)
|
36
|
+
attributes[attribute] = :float
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param attribute [Symbol] the name of the attribute on {#column}
|
40
|
+
# for which to generate a DateTime-type accessor
|
41
|
+
#
|
42
|
+
def datetime(attribute)
|
43
|
+
attributes[attribute] = :datetime
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param attribute [Symbol] the name of the attribute on {#column}
|
47
|
+
# for which to generate a Boolean-type accessor
|
48
|
+
#
|
49
|
+
def boolean(attribute)
|
50
|
+
attributes[attribute] = :boolean
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Iterates over all defined {#attributes} and defines the
|
56
|
+
# necessary accessors for them.
|
57
|
+
#
|
58
|
+
# @param klass [Class] the class to define the accessors on
|
59
|
+
#
|
60
|
+
def configure(klass)
|
61
|
+
attributes.each do |attribute, type|
|
62
|
+
StoreSchema::AccessorDefiner
|
63
|
+
.new(klass, column, type, attribute).define
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
class StoreSchema::Converter::Boolean
|
4
|
+
include StoreSchema::Converter::Base
|
5
|
+
|
6
|
+
# @return [String] the database representation of a true value.
|
7
|
+
#
|
8
|
+
DB_TRUE_VALUE = "t"
|
9
|
+
|
10
|
+
# @return [Array] all the values that are considered to be truthy.
|
11
|
+
#
|
12
|
+
TRUE_VALUES = [true, 1, "1", "t", "T", "true", "TRUE", "on", "ON"]
|
13
|
+
|
14
|
+
# @return [Array] all the values that are considered to be falsy.
|
15
|
+
#
|
16
|
+
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
|
17
|
+
|
18
|
+
# @return [Object]
|
19
|
+
#
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
# @param [Object] value
|
23
|
+
#
|
24
|
+
def initialize(value)
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
# Converts the {#value} to a database-storable value.
|
29
|
+
#
|
30
|
+
# @return [String, false] false if {#value} is an invalid date-type.
|
31
|
+
#
|
32
|
+
def to_db
|
33
|
+
if TRUE_VALUES.include?(value)
|
34
|
+
"t"
|
35
|
+
elsif FALSE_VALUES.include?(value)
|
36
|
+
"f"
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Converts the {#value} to a Ruby-type value.
|
43
|
+
#
|
44
|
+
# @return [true, false]
|
45
|
+
#
|
46
|
+
def from_db
|
47
|
+
value == DB_TRUE_VALUE
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
class StoreSchema::Converter::DateTime
|
4
|
+
include StoreSchema::Converter::Base
|
5
|
+
|
6
|
+
# @return [String] the database format for storing a DateTime object.
|
7
|
+
#
|
8
|
+
DATETIME_DB_FORMAT = "%Y-%m-%d %H:%M:%S.%N"
|
9
|
+
|
10
|
+
# Converts the {#value} to a database-storable value.
|
11
|
+
#
|
12
|
+
# @return [String, false] false if {#value} is an invalid date-type.
|
13
|
+
#
|
14
|
+
def to_db
|
15
|
+
begin
|
16
|
+
case value
|
17
|
+
when ::DateTime, ::Date
|
18
|
+
value.strftime(DATETIME_DB_FORMAT)
|
19
|
+
when ::Time
|
20
|
+
value.utc.strftime(DATETIME_DB_FORMAT)
|
21
|
+
when ::String
|
22
|
+
::DateTime.parse(value).strftime(DATETIME_DB_FORMAT)
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Converts the {#value} to a Ruby-type value.
|
32
|
+
#
|
33
|
+
# @return [DateTime]
|
34
|
+
#
|
35
|
+
def from_db
|
36
|
+
::DateTime.parse(value)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
class StoreSchema::Converter::Float
|
4
|
+
include StoreSchema::Converter::Base
|
5
|
+
|
6
|
+
# Converts the {#value} to a database-storable value.
|
7
|
+
#
|
8
|
+
# @return [String, false] false if {#value} is an invalid date-type.
|
9
|
+
#
|
10
|
+
def to_db
|
11
|
+
case value
|
12
|
+
when ::Integer
|
13
|
+
value.to_f.to_s
|
14
|
+
when ::Float
|
15
|
+
value.to_s
|
16
|
+
when ::String
|
17
|
+
if value =~ /^\d+|\d+\.\d+$/
|
18
|
+
value.to_f.to_s
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
else
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Converts the {#value} to a Ruby-type value.
|
28
|
+
#
|
29
|
+
# @return [Float]
|
30
|
+
#
|
31
|
+
def from_db
|
32
|
+
value.to_f
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
class StoreSchema::Converter::Integer
|
4
|
+
include StoreSchema::Converter::Base
|
5
|
+
|
6
|
+
# Converts the {#value} to a database-storable value.
|
7
|
+
#
|
8
|
+
# @return [String, false] false if {#value} is an invalid date-type.
|
9
|
+
#
|
10
|
+
def to_db
|
11
|
+
case value
|
12
|
+
when ::Integer
|
13
|
+
value.to_s
|
14
|
+
when ::String
|
15
|
+
if value =~ /^\d+$/
|
16
|
+
value
|
17
|
+
else
|
18
|
+
false
|
19
|
+
end
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Converts the {#value} to a Ruby-type value.
|
26
|
+
#
|
27
|
+
# @return [Integer]
|
28
|
+
#
|
29
|
+
def from_db
|
30
|
+
value.to_i
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
class StoreSchema::Converter::String
|
4
|
+
include StoreSchema::Converter::Base
|
5
|
+
|
6
|
+
# Simply returns {#value} if it's a String.
|
7
|
+
#
|
8
|
+
# @return [String, false] false if {#value} is an invalid date-type.
|
9
|
+
#
|
10
|
+
def to_db
|
11
|
+
if value.is_a?(::String)
|
12
|
+
value
|
13
|
+
else
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Simply returns {#value} since it's already a String-type.
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
#
|
22
|
+
def from_db
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class StoreSchema::Converter
|
2
|
+
require_relative "converter/string"
|
3
|
+
require_relative "converter/integer"
|
4
|
+
require_relative "converter/float"
|
5
|
+
require_relative "converter/date_time"
|
6
|
+
require_relative "converter/boolean"
|
7
|
+
|
8
|
+
# @return [Hash] a mapping between the configuration block
|
9
|
+
# and the converter classes.
|
10
|
+
#
|
11
|
+
MAPPING = {
|
12
|
+
string: String,
|
13
|
+
integer: Integer,
|
14
|
+
float: Float,
|
15
|
+
datetime: DateTime,
|
16
|
+
boolean: Boolean
|
17
|
+
}
|
18
|
+
|
19
|
+
# @return [Object]
|
20
|
+
#
|
21
|
+
attr_reader :value
|
22
|
+
|
23
|
+
# @return [Symbol]
|
24
|
+
#
|
25
|
+
attr_reader :type
|
26
|
+
|
27
|
+
# @param value [Object] any kind of value that should be stored
|
28
|
+
# @param type [Symbol] the type of the value
|
29
|
+
#
|
30
|
+
def initialize(value, type)
|
31
|
+
@value = value
|
32
|
+
@type = type
|
33
|
+
end
|
34
|
+
|
35
|
+
# Converts {#value} from a Ruby-type value to a database-storable value.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
#
|
39
|
+
def to_db
|
40
|
+
MAPPING[type].new(value).to_db
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts {#value} from a database-storable value to a Ruby-type value.
|
44
|
+
#
|
45
|
+
# @return [Object]
|
46
|
+
#
|
47
|
+
def from_db
|
48
|
+
MAPPING[type].new(value).from_db
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module StoreSchema::Module
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # Gemfile
|
12
|
+
# gem "store_schema"
|
13
|
+
#
|
14
|
+
# # app/models/project.rb
|
15
|
+
# class Website < ActiveRecord::Base
|
16
|
+
#
|
17
|
+
# store_schema :config do |s|
|
18
|
+
# s.string :name
|
19
|
+
# s.integer :visitors
|
20
|
+
# s.float :apdex
|
21
|
+
# s.boolean :ssl
|
22
|
+
# s.datetime :published_at
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @param column [Symbol] name of the table column
|
27
|
+
# @param block [Proc] the configuration block
|
28
|
+
#
|
29
|
+
def store_schema(column, &block)
|
30
|
+
StoreSchema::Configuration.new(column).tap do |config|
|
31
|
+
yield(config)
|
32
|
+
config.send(:configure, self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/store_schema.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module StoreSchema
|
2
|
+
require "store_schema/accessor_definer"
|
3
|
+
require "store_schema/configuration"
|
4
|
+
require "store_schema/converter"
|
5
|
+
require "store_schema/module"
|
6
|
+
require "store_schema/version"
|
7
|
+
end
|
8
|
+
|
9
|
+
if defined?(ActiveRecord::Base)
|
10
|
+
ActiveRecord::Base.send(:include, StoreSchema::Module)
|
11
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "StoreSchema" do
|
4
|
+
|
5
|
+
let(:website) { Website.new }
|
6
|
+
|
7
|
+
describe "nil" do
|
8
|
+
|
9
|
+
it "should stay nil" do
|
10
|
+
website.update_attribute(:name, nil)
|
11
|
+
expect(website.reload.name).to be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "string" do
|
16
|
+
|
17
|
+
it "should remain a string" do
|
18
|
+
website.update_attribute(:name, "Store Schema")
|
19
|
+
expect(website.reload.name).to eq("Store Schema")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "does not accept invalid data types" do
|
23
|
+
expect { website.update_attribute(:name, true) }
|
24
|
+
.to raise_error(
|
25
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
26
|
+
"true (TrueClass) for Website#config.name (string)"
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "integer" do
|
32
|
+
|
33
|
+
it "should cast to string and back to integer" do
|
34
|
+
website.update_attribute(:visitors, 1337)
|
35
|
+
expect(website.config["visitors"]).to eq("1337")
|
36
|
+
expect(website.visitors).to eq(1337)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should accept a string value of a digit" do
|
40
|
+
website.update_attribute(:visitors, "1337")
|
41
|
+
expect(website.config["visitors"]).to eq("1337")
|
42
|
+
expect(website.visitors).to eq(1337)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "does not accept invalid string formats" do
|
46
|
+
expect { website.update_attribute(:visitors, "abc") }
|
47
|
+
.to raise_error(
|
48
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
49
|
+
"abc (String) for Website#config.visitors (integer)"
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does not accept invalid data types" do
|
54
|
+
expect { website.update_attribute(:visitors, true) }
|
55
|
+
.to raise_error(
|
56
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
57
|
+
"true (TrueClass) for Website#config.visitors (integer)"
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "float" do
|
63
|
+
|
64
|
+
it "should cast to string and back to float" do
|
65
|
+
website.update_attribute(:apdex, 0.9)
|
66
|
+
expect(website.config["apdex"]).to eq("0.9")
|
67
|
+
expect(website.apdex).to eq(0.9)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should accept a string value of a float" do
|
71
|
+
website.update_attribute(:apdex, "0.9")
|
72
|
+
expect(website.config["apdex"]).to eq("0.9")
|
73
|
+
expect(website.apdex).to eq(0.9)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should accept an integer value" do
|
77
|
+
website.update_attribute(:apdex, 1)
|
78
|
+
expect(website.config["apdex"]).to eq("1.0")
|
79
|
+
expect(website.apdex).to eq(1.0)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should accept a string value of an integer" do
|
83
|
+
website.update_attribute(:apdex, "1")
|
84
|
+
expect(website.config["apdex"]).to eq("1.0")
|
85
|
+
expect(website.apdex).to eq(1.0)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not accept invalid string formats" do
|
89
|
+
expect { website.update_attribute(:apdex, "abc") }
|
90
|
+
.to raise_error(
|
91
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
92
|
+
"abc (String) for Website#config.apdex (float)"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "does not accept invalid data types" do
|
97
|
+
expect { website.update_attribute(:apdex, true) }
|
98
|
+
.to raise_error(
|
99
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
100
|
+
"true (TrueClass) for Website#config.apdex (float)"
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "boolean" do
|
106
|
+
|
107
|
+
it "should cast to string and back to boolean" do
|
108
|
+
StoreSchema::Converter::Boolean::TRUE_VALUES.each do |value|
|
109
|
+
website.update_attribute(:ssl, value)
|
110
|
+
expect(website.config["ssl"]).to eq("t")
|
111
|
+
expect(website.ssl).to eq(true)
|
112
|
+
end
|
113
|
+
|
114
|
+
StoreSchema::Converter::Boolean::FALSE_VALUES.each do |value|
|
115
|
+
website.update_attribute(:ssl, value)
|
116
|
+
expect(website.config["ssl"]).to eq("f")
|
117
|
+
expect(website.ssl).to eq(false)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "does not accept invalid data types" do
|
122
|
+
expect { website.update_attribute(:ssl, "abc") }
|
123
|
+
.to raise_error(
|
124
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
125
|
+
"abc (String) for Website#config.ssl (boolean)"
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "datetime" do
|
131
|
+
|
132
|
+
it "should cast Date to string and back to datetime" do
|
133
|
+
value = Date.new(2020)
|
134
|
+
website.update_attribute(:published_at, value)
|
135
|
+
expect(website.config["published_at"]).to eq("2020-01-01 00:00:00.000000000")
|
136
|
+
expect(website.published_at).to eq("Wed, 01 Jan 2020 00:00:00.000000000 +0000")
|
137
|
+
expect(website.published_at.class).to eq(DateTime)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should cast Time to string and back to datetime" do
|
141
|
+
value = Time.utc(2020)
|
142
|
+
website.update_attribute(:published_at, value)
|
143
|
+
expect(website.config["published_at"]).to eq("2020-01-01 00:00:00.000000000")
|
144
|
+
expect(website.published_at).to eq("Wed, 01 Jan 2020 00:00:00.000000000 +0000")
|
145
|
+
expect(website.published_at.class).to eq(DateTime)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should cast DateTime to string and back to datetime" do
|
149
|
+
value = DateTime.new(2020)
|
150
|
+
website.update_attribute(:published_at, value)
|
151
|
+
expect(website.config["published_at"]).to eq("2020-01-01 00:00:00.000000000")
|
152
|
+
expect(website.published_at).to eq("Wed, 01 Jan 2020 00:00:00.000000000 +0000")
|
153
|
+
expect(website.published_at.class).to eq(DateTime)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "does not accept invalid string formats" do
|
157
|
+
expect { website.update_attribute(:published_at, "abc") }
|
158
|
+
.to raise_error(
|
159
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
160
|
+
"abc (String) for Website#config.published_at (datetime)"
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "does not accept invalid data types" do
|
165
|
+
expect { website.update_attribute(:published_at, true) }
|
166
|
+
.to raise_error(
|
167
|
+
StoreSchema::AccessorDefiner::InvalidValueType,
|
168
|
+
"true (TrueClass) for Website#config.published_at (datetime)"
|
169
|
+
)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
2
|
+
require File.expand_path("../support/env", __FILE__)
|
3
|
+
|
4
|
+
require "database_cleaner"
|
5
|
+
require "simplecov"
|
6
|
+
SimpleCov.start
|
7
|
+
|
8
|
+
require "store_schema"
|
9
|
+
require File.expand_path("../support/models", __FILE__)
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.mock_framework = :mocha
|
13
|
+
|
14
|
+
config.before do
|
15
|
+
DatabaseCleaner.start
|
16
|
+
end
|
17
|
+
|
18
|
+
config.after do
|
19
|
+
DatabaseCleaner.clean
|
20
|
+
end
|
21
|
+
end
|
data/spec/support/db.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
ActiveRecord::Base.logger = Logger.new(LOG_PATH)
|
2
|
+
ActiveRecord::Base.establish_connection(
|
3
|
+
adapter: "sqlite3", database: ":memory:"
|
4
|
+
)
|
5
|
+
|
6
|
+
class Schema < ActiveRecord::Migration
|
7
|
+
|
8
|
+
def change
|
9
|
+
create_table :websites do |t|
|
10
|
+
t.text :config
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
silence_stream(STDOUT) do
|
16
|
+
Schema.new.change
|
17
|
+
end
|
data/spec/support/env.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "logger"
|
3
|
+
require "pry"
|
4
|
+
require "sqlite3"
|
5
|
+
require "active_record"
|
6
|
+
|
7
|
+
ROOT_PATH = File.expand_path("../../..", __FILE__)
|
8
|
+
SPEC_PATH = File.join(ROOT_PATH, "spec")
|
9
|
+
TMP_PATH = File.join(ROOT_PATH, "tmp")
|
10
|
+
LOG_PATH = File.join(TMP_PATH, "store_schema.log")
|
11
|
+
|
12
|
+
FileUtils.mkdir_p(TMP_PATH)
|
13
|
+
|
14
|
+
require "#{SPEC_PATH}/support/db"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "store_schema/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "store_schema"
|
7
|
+
spec.version = StoreSchema::VERSION
|
8
|
+
spec.authors = ["Michael van Rooijen"]
|
9
|
+
spec.email = ["michael@vanrooijen.io"]
|
10
|
+
spec.summary = %q{Enhances ActiveRecord::Base.store_accessor with data conversion capabilities.}
|
11
|
+
spec.homepage = "http://meskyanichi.github.io/store_schema/"
|
12
|
+
spec.license = "MIT"
|
13
|
+
|
14
|
+
spec.files = `git ls-files -z`.split("\x0")
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_dependency "activerecord", ">= 4.0.0"
|
20
|
+
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency "rspec"
|
23
|
+
spec.add_development_dependency "mocha"
|
24
|
+
spec.add_development_dependency "sqlite3"
|
25
|
+
spec.add_development_dependency "database_cleaner"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "simplecov"
|
28
|
+
spec.add_development_dependency "yard"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: store_schema
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael van Rooijen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: database_cleaner
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yard
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description:
|
154
|
+
email:
|
155
|
+
- michael@vanrooijen.io
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gemfiles/4.0.gemfile"
|
161
|
+
- ".gemfiles/4.1.gemfile"
|
162
|
+
- ".gemfiles/4.2.gemfile"
|
163
|
+
- ".gitignore"
|
164
|
+
- ".rspec"
|
165
|
+
- ".travis.yml"
|
166
|
+
- Gemfile
|
167
|
+
- LICENSE
|
168
|
+
- README.md
|
169
|
+
- Rakefile
|
170
|
+
- lib/store_schema.rb
|
171
|
+
- lib/store_schema/accessor_definer.rb
|
172
|
+
- lib/store_schema/configuration.rb
|
173
|
+
- lib/store_schema/converter.rb
|
174
|
+
- lib/store_schema/converter/base.rb
|
175
|
+
- lib/store_schema/converter/boolean.rb
|
176
|
+
- lib/store_schema/converter/date_time.rb
|
177
|
+
- lib/store_schema/converter/float.rb
|
178
|
+
- lib/store_schema/converter/integer.rb
|
179
|
+
- lib/store_schema/converter/string.rb
|
180
|
+
- lib/store_schema/module.rb
|
181
|
+
- lib/store_schema/version.rb
|
182
|
+
- spec/lib/casted_store_accessor_spec.rb
|
183
|
+
- spec/spec_helper.rb
|
184
|
+
- spec/support/db.rb
|
185
|
+
- spec/support/env.rb
|
186
|
+
- spec/support/models.rb
|
187
|
+
- store_schema.gemspec
|
188
|
+
homepage: http://meskyanichi.github.io/store_schema/
|
189
|
+
licenses:
|
190
|
+
- MIT
|
191
|
+
metadata: {}
|
192
|
+
post_install_message:
|
193
|
+
rdoc_options: []
|
194
|
+
require_paths:
|
195
|
+
- lib
|
196
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
requirements: []
|
207
|
+
rubyforge_project:
|
208
|
+
rubygems_version: 2.4.1
|
209
|
+
signing_key:
|
210
|
+
specification_version: 4
|
211
|
+
summary: Enhances ActiveRecord::Base.store_accessor with data conversion capabilities.
|
212
|
+
test_files:
|
213
|
+
- spec/lib/casted_store_accessor_spec.rb
|
214
|
+
- spec/spec_helper.rb
|
215
|
+
- spec/support/db.rb
|
216
|
+
- spec/support/env.rb
|
217
|
+
- spec/support/models.rb
|
218
|
+
has_rdoc:
|