attributary 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +6 -0
- data/README.md +127 -0
- data/Rakefile +2 -0
- data/attributary.gemspec +24 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/.DS_Store +0 -0
- data/lib/attributary.rb +9 -0
- data/lib/attributary/.DS_Store +0 -0
- data/lib/attributary/config.rb +27 -0
- data/lib/attributary/core_ext.rb +15 -0
- data/lib/attributary/dsl.rb +87 -0
- data/lib/attributary/initializer.rb +13 -0
- data/lib/attributary/type.rb +18 -0
- data/lib/attributary/types/array_type.rb +9 -0
- data/lib/attributary/types/big_decimal_type.rb +9 -0
- data/lib/attributary/types/boolean_type.rb +13 -0
- data/lib/attributary/types/float_type.rb +9 -0
- data/lib/attributary/types/hash_type.rb +9 -0
- data/lib/attributary/types/integer_type.rb +9 -0
- data/lib/attributary/types/string_type.rb +9 -0
- data/lib/attributary/types/symbol_type.rb +9 -0
- data/lib/attributary/version.rb +3 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ebdff0c364b0480e2c79d90df50064f2b015400
|
4
|
+
data.tar.gz: cef7eccd653b8c77ea68aa3f08a40ab89787ab63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0aa7ee051f7a870076ff468b1f6b1a9b4ab91a1342e2e3c5f876c3fb7a024affd4b8a3b279cc933a2a340161444082f9702025a4d6b4e725d3682f747a707e51
|
7
|
+
data.tar.gz: d13c1daefa1c490e0a9fe70ac1dfbb626c477525716013bf1467212688b7c1f72b17821b857fa7679b5c05a730db844da493fa8923464e5556181199ee56a3b3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# Attributary
|
2
|
+
|
3
|
+
Like `ActiveModel::Attributes` but not. No dependencies.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'attributary'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install attributary
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Configuration
|
24
|
+
|
25
|
+
Attributary.configure do |c|
|
26
|
+
c.dsl_name = :donkey # defaults to :attrubute
|
27
|
+
c.strict_mode = false # set this to `true` to skip casting in the writer method (raises TypeError)
|
28
|
+
end
|
29
|
+
|
30
|
+
### Actually using it
|
31
|
+
|
32
|
+
class Character
|
33
|
+
include Attributary::DSL
|
34
|
+
|
35
|
+
donkey :gender, :symbol, default: :male
|
36
|
+
end
|
37
|
+
|
38
|
+
character = Character.new
|
39
|
+
puts character.gender # :male
|
40
|
+
character.gender = 'female'
|
41
|
+
puts character.gender # :female
|
42
|
+
|
43
|
+
### Initializing
|
44
|
+
|
45
|
+
Want to initialize? Cool.
|
46
|
+
|
47
|
+
class Character
|
48
|
+
include Attributary::Initializer
|
49
|
+
include Attributary::DSL
|
50
|
+
|
51
|
+
donkey :gender, :symbol, default: :male
|
52
|
+
end
|
53
|
+
|
54
|
+
character = Character.new(gender: :male)
|
55
|
+
puts character.gender # :male
|
56
|
+
|
57
|
+
Have to initialize other stuff? Send a hash to attributary_initialize
|
58
|
+
|
59
|
+
class Character
|
60
|
+
include Attributary::Initializer
|
61
|
+
include Attributary::DSL
|
62
|
+
|
63
|
+
donkey :gender, :symbol, default: :male
|
64
|
+
|
65
|
+
def initialize(name, attributary_attributes = {})
|
66
|
+
@name = name
|
67
|
+
attributary_initialize(attributary_attributes)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
character = Character.new("Charlie", gender: :male)
|
72
|
+
puts character.gender # :male
|
73
|
+
|
74
|
+
### Validations
|
75
|
+
|
76
|
+
There are two types of validations. You can pass a `:collection` option, and/or you can pass a `:validates` option.
|
77
|
+
|
78
|
+
#### Using `:collection`
|
79
|
+
|
80
|
+
Simply pass an array of the possible options for the attribute.
|
81
|
+
|
82
|
+
class Character
|
83
|
+
include Attributary::DSL
|
84
|
+
|
85
|
+
donkey :gender, :symbol, default: :male, collection: [:male, :female]
|
86
|
+
end
|
87
|
+
|
88
|
+
character = Character.new("Charlie", gender: :male)
|
89
|
+
puts character.gender # :male
|
90
|
+
character.gender = :left # raises CollectionValidationError
|
91
|
+
character.gender = :female
|
92
|
+
puts character.gender # :female
|
93
|
+
character.gender = 'male' # gets casted correctly, and doesn't raise an error. Turn this off with strict_mode
|
94
|
+
|
95
|
+
#### Using `:validates`
|
96
|
+
|
97
|
+
Pass a proc or a method name.
|
98
|
+
|
99
|
+
class Character
|
100
|
+
include Attributary::DSL
|
101
|
+
|
102
|
+
donkey :gender, :symbol, default: :male, validates: proc { |value| [:male, :female].include?(value) }
|
103
|
+
end
|
104
|
+
|
105
|
+
character = Character.new("Charlie", gender: :male)
|
106
|
+
puts character.gender # :male
|
107
|
+
character.gender = :left # raises CollectionValidationError
|
108
|
+
character.gender = 'female' # gets casted correctly, and doesn't raise an error
|
109
|
+
|
110
|
+
|
111
|
+
### Types
|
112
|
+
|
113
|
+
Supports some really naive typecasting. [See the supported types](https://github.com/joshmn/attributary/tree/master/lib/attributary/types). Create your own by inheriting from `Attributary::Types` and naming it like `ClassNameType`
|
114
|
+
|
115
|
+
module Attributary
|
116
|
+
module Types
|
117
|
+
class FriendType < Type
|
118
|
+
def self.cast_to(value)
|
119
|
+
Foe.new(value)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
## Contributing
|
126
|
+
|
127
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/joshmn/attributary
|
data/Rakefile
ADDED
data/attributary.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'attributary/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'attributary'
|
7
|
+
spec.version = Attributary::VERSION
|
8
|
+
spec.authors = ['Josh Brody']
|
9
|
+
spec.email = ['josh@josh.mn']
|
10
|
+
|
11
|
+
spec.summary = 'Like ActiveModel::Attributes but less fluffy and more attribute-y.'
|
12
|
+
spec.description = 'Like `ActiveModel::Attributes` but less fluffy and more attribute-y.'
|
13
|
+
spec.homepage = 'https://github.com/joshmn/attributary'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'attributary'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/attributary.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative 'attributary/config'
|
2
|
+
require_relative 'attributary/core_ext'
|
3
|
+
require_relative 'attributary/type'
|
4
|
+
require_relative 'attributary/initializer'
|
5
|
+
require_relative 'attributary/dsl'
|
6
|
+
require_relative 'attributary/version'
|
7
|
+
|
8
|
+
module Attributary
|
9
|
+
end
|
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Attributary
|
2
|
+
def self.configuration
|
3
|
+
@configuration || Config.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configuration=(val)
|
7
|
+
@configuration = val
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
self.configuration ||= Config.new
|
12
|
+
yield(configuration)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Config
|
16
|
+
attr_accessor :dsl_name, :strict_mode
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@dsl_name = :attribute
|
20
|
+
@strict_mode = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def strict_mode?
|
24
|
+
@strict_mode
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Attributary
|
2
|
+
module DSL
|
3
|
+
class ValidationError < StandardError; end
|
4
|
+
class CollectionValidationError < StandardError; end
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def _attributary_attribute_set
|
12
|
+
@_attributary_attribute_set ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def _attributary_attributes
|
16
|
+
hash = {}
|
17
|
+
_attributary_attribute_set.keys.each do |k|
|
18
|
+
hash[k] = instance_variable_get(:"@#{k}")
|
19
|
+
end
|
20
|
+
hash
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method(Attributary.configuration.dsl_name) do |name, type, options = {}|
|
24
|
+
options[:type] = type
|
25
|
+
_attributary_attribute_set[name] = options
|
26
|
+
_attributary_reader(name, type, options)
|
27
|
+
_attributary_writer(name, type, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _attributary_reader(name, type, options)
|
31
|
+
define_method(name) do
|
32
|
+
instance_variable_get(:"@#{name}") || if options[:default].is_a?(Proc)
|
33
|
+
options[:default].call
|
34
|
+
else
|
35
|
+
options[:default]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
if type == :boolean
|
39
|
+
define_method("#{name}?") do
|
40
|
+
send(name.to_s)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _attributary_writer(name, type, options)
|
46
|
+
define_method("#{name}=") do |value|
|
47
|
+
value = self.class._attributary_cast_to(type, value) unless Attributary.configuration.strict_mode?
|
48
|
+
self.class._attributary_check_collection(value, options[:collection]) if options[:collection].is_a?(Array)
|
49
|
+
self.class._attributary_validate_attribute(value, options[:validates])
|
50
|
+
instance_variable_set(:"@#{name}", value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def _attributary_check_collection(value, collection)
|
55
|
+
unless collection.include?(value)
|
56
|
+
raise CollectionValidationError, "Value `#{value}' is not in the collection #{collection}."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def _attributary_validate_attribute(value, validator)
|
61
|
+
return true if validator.nil?
|
62
|
+
raise ValidationError, 'Validator failed.' unless validator.call(value)
|
63
|
+
end
|
64
|
+
|
65
|
+
def _attributary_cast_to(type, value)
|
66
|
+
cast_klass = _attributary_cast_class(type)
|
67
|
+
cast_klass.cast_to(value)
|
68
|
+
end
|
69
|
+
|
70
|
+
def _attributary_cast_class(type)
|
71
|
+
cast_klass_name = _attributary_cast_class_name(type)
|
72
|
+
cast_klass = cast_klass_name.safe_constantize
|
73
|
+
if cast_klass.nil?
|
74
|
+
raise NameError, "#{cast_klass_name} is not a valid type."
|
75
|
+
end
|
76
|
+
unless cast_klass.respond_to?(:cast_to)
|
77
|
+
raise NoMethodError, "#{cast_klass} should have a class-method of cast_to"
|
78
|
+
end
|
79
|
+
cast_klass
|
80
|
+
end
|
81
|
+
|
82
|
+
def _attributary_cast_class_name(type)
|
83
|
+
"Attributary::Types::#{type.to_s.split('_').map(&:capitalize).join}Type"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Attributary
|
2
|
+
module Types
|
3
|
+
class Type
|
4
|
+
def self.cast_to(value)
|
5
|
+
value
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require_relative 'types/array_type'
|
12
|
+
require_relative 'types/big_decimal_type'
|
13
|
+
require_relative 'types/boolean_type'
|
14
|
+
require_relative 'types/float_type'
|
15
|
+
require_relative 'types/hash_type'
|
16
|
+
require_relative 'types/integer_type'
|
17
|
+
require_relative 'types/string_type'
|
18
|
+
require_relative 'types/symbol_type'
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attributary
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Josh Brody
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-06-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Like `ActiveModel::Attributes` but less fluffy and more attribute-y.
|
42
|
+
email:
|
43
|
+
- josh@josh.mn
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- attributary.gemspec
|
53
|
+
- bin/console
|
54
|
+
- bin/setup
|
55
|
+
- lib/.DS_Store
|
56
|
+
- lib/attributary.rb
|
57
|
+
- lib/attributary/.DS_Store
|
58
|
+
- lib/attributary/config.rb
|
59
|
+
- lib/attributary/core_ext.rb
|
60
|
+
- lib/attributary/dsl.rb
|
61
|
+
- lib/attributary/initializer.rb
|
62
|
+
- lib/attributary/type.rb
|
63
|
+
- lib/attributary/types/array_type.rb
|
64
|
+
- lib/attributary/types/big_decimal_type.rb
|
65
|
+
- lib/attributary/types/boolean_type.rb
|
66
|
+
- lib/attributary/types/float_type.rb
|
67
|
+
- lib/attributary/types/hash_type.rb
|
68
|
+
- lib/attributary/types/integer_type.rb
|
69
|
+
- lib/attributary/types/string_type.rb
|
70
|
+
- lib/attributary/types/symbol_type.rb
|
71
|
+
- lib/attributary/version.rb
|
72
|
+
homepage: https://github.com/joshmn/attributary
|
73
|
+
licenses: []
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.6.13
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Like ActiveModel::Attributes but less fluffy and more attribute-y.
|
95
|
+
test_files: []
|