static_models 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14b52ac6a5f6d2ea3a9cd809e96dc9a5d3a9bd84
4
- data.tar.gz: 0fe26ca5989a19dbdf39805a156e4dd4a16509dc
3
+ metadata.gz: 65dff81c399c94a47e52447d832acd3cff5922d7
4
+ data.tar.gz: a736899f5666ee1281d50e29a457c1b6faca1547
5
5
  SHA512:
6
- metadata.gz: 8d2a70e05c48350c0a4c48b3924403a511358dab5f09c9fd9bd71a2cfe84835c938b09324ac06cdf4610c11878e4218cb49848bb29311220f3bd8148d982ec27
7
- data.tar.gz: 0559dd452091ec6fd0954d10eb81d70a1450a2ce9e2efd4baf0f8b78890dacb90ad6e536ada21cadbcce89db90b6f1c4b5f7aded2ac559e71572158f8141607b
6
+ metadata.gz: 0af88921adb55e963701874d2990d9bac7779202a40417e44847d3c60170bfd0a168e943e38469a4546e7f29566e7954a01688635d12da843430bb0025363cc1
7
+ data.tar.gz: 2123b43bf3c3948948e2531a9434a6a789952aab7e39eb9270a04c9c569eb564d922c7f154b10adcff8dd13e0f23bd5d8c26e5fc7d745b836828036afab6267d
data/README.md CHANGED
@@ -22,6 +22,8 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
+ ### Defining your models
26
+
25
27
  ```ruby
26
28
  # We're modelling Dogs, each of them has a Breed.
27
29
  # We support a static set of Breeds.
@@ -30,17 +32,18 @@ Or install it yourself as:
30
32
  # Enhance Breed to be a StaticModel
31
33
  include StaticModels::Model
32
34
 
33
- # Actually define the breeds we support using a Hash
34
- # Keys are the 'id' attribute of each model. Must be Integers.
35
- # Values are the 'code' attribute. Must be Symbols, and unique.
36
- # If you want your model to have extra attributes, make the value
37
- # be an Array of 2 elements: [Symbol, Hash].
38
- static_models(
39
- 1 => :collie,
40
- 2 => :foxhound,
41
- 6 => [:corgi, height: 'short'],
42
- 7 => [:doberman, height: 'tall']
43
- )
35
+ # Our StaticModel instances can be defined as a table.
36
+ # The first two columns are special:
37
+ # 'id' must be a Fixnum, and will be used internally as primary key.
38
+ # 'code' must be a Symbol, and will be used as a friendlier ID.
39
+ # Class methods will be created to fetch a StaticModel instance by code.
40
+ static_models_dense [
41
+ [:id, :code, :height ],
42
+ [1, :collie, nil ],
43
+ [2, :foxhound, nil ],
44
+ [6, :corgi, 'short' ],
45
+ [7, :doberman, 'tall' ],
46
+ ]
44
47
  end
45
48
 
46
49
  # You can find your Breed.
@@ -63,7 +66,7 @@ Or install it yourself as:
63
66
  Breed.doberman
64
67
  ]
65
68
 
66
- # The low level 'values' dictionary is public.
69
+ # A low level 'values' dictionary is public.
67
70
  Breed.values.should == {
68
71
  1 => Breed.collie,
69
72
  2 => Breed.foxhound,
@@ -71,6 +74,23 @@ Or install it yourself as:
71
74
  7 => Breed.doberman
72
75
  }
73
76
 
77
+ # An alternative syntax is supported to use with sparse attribute definitions
78
+ # Here's a definition of Breed with sparse attributes.
79
+ class SparseBreed
80
+ include StaticModels::Model
81
+ static_models_sparse [
82
+ [1, :collie],
83
+ [2, :foxhound],
84
+ [6, :corgi, height: 'short'],
85
+ [7, :doberman, height: 'tall'],
86
+ ]
87
+ end
88
+ ```
89
+
90
+ ### PORO's and ActiveRecords can belongs_to a StaticModel
91
+
92
+ ```ruby
93
+
74
94
  # You point to your StaticModels like an ActiveRecords belongs_to association
75
95
  # Setting a Breed will update a breed_id attribute.
76
96
  class Dog
@@ -1,3 +1,3 @@
1
1
  module StaticModels
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/static_models.rb CHANGED
@@ -7,45 +7,65 @@ module StaticModels
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do |i|
10
- cattr_accessor :values
10
+ cattr_accessor :values, :id_column, :code_column
11
11
 
12
- def initialize(id, code, *args)
13
- self.id = id
14
- self.code = code
15
- unless args.empty?
16
- args.first.each{|name,value| send("#{name}=", value) }
17
- end
12
+ def initialize(attributes)
13
+ attributes.each{|name,value| send("#{name}=", value) }
18
14
  end
19
15
 
20
- def to_s; code.to_s; end
21
- def to_i; id; end
22
- def name; code; end
16
+ def name; send(self.class.code_column); end
17
+ def to_s; name.to_s; end
18
+ def to_i; send(self.class.id_column); end
23
19
  end
24
20
 
25
21
  class_methods do
26
- def static_models(new_values)
27
- attr_accessor :id, :code
22
+ def static_models_dense(table)
23
+ columns = table.first
24
+ hashes = table[1..-1].collect do |row|
25
+ Hash[*columns.zip(row).flatten(1)]
26
+ end
28
27
 
29
- self.values = {}
30
- new_values.each do |k,v|
31
- unless k.is_a?(Integer)
32
- raise TypeError.new("Expected Integer for keys, found #{k.class}")
33
- end
28
+ static_models_hashes columns, hashes
29
+ end
34
30
 
35
- if v.is_a?(Array)
36
- unless v.size == 2 && v.first.is_a?(Symbol) && v.last.is_a?(Hash)
37
- raise TypeError.new("Expected [Symbol, Hash] found #{v.class}")
38
- end
39
- attr_accessor *v.last.keys
40
- else
41
- unless v.is_a?(Symbol)
42
- raise TypeError.new("Expected Symbol, found #{v.class}")
43
- end
31
+ def static_models_sparse(table)
32
+ table.each do |row|
33
+ expected = row.size == 2 ? [Fixnum, Symbol] : [Fixnum, Symbol, Hash]
34
+
35
+ if row.collect(&:class) != expected
36
+ raise ValueError.new("Invalid row #{row}, expected #{expected}")
44
37
  end
45
- item = new(k, *v)
46
- values[k] = item
38
+ end
39
+
40
+ columns = table.select{|r| r.size == 3}
41
+ .collect{|r| r.last.keys }.flatten(1).uniq
47
42
 
48
- raise DuplicateCodes.new if singleton_methods.include?(item.code)
43
+ hashes = table.collect{ |r| (r[2] || {}).merge(id: r[0], code: r[1]) }
44
+ static_models_hashes ([:id, :code] + columns), hashes
45
+ end
46
+
47
+ def static_models_hashes(columns, hashes)
48
+ unless columns.all?{|c| c.is_a?(Symbol)}
49
+ raise ValueError.new("Table column names must all be Symbols")
50
+ end
51
+
52
+ unless hashes.all?{|h| h[:id].is_a?(Fixnum)}
53
+ raise ValueError.new("Ids must be integers")
54
+ end
55
+
56
+ unless hashes.all?{|h| h[:code].is_a?(Symbol)}
57
+ raise ValueError.new("Codes must be Symbols")
58
+ end
59
+
60
+ attr_accessor *columns
61
+ self.id_column = columns[0]
62
+ self.code_column = columns[1]
63
+
64
+ self.values = {}
65
+ hashes.each do |hash|
66
+ item = new(hash)
67
+ values[item.id] = item
68
+ raise ValueError.new if singleton_methods.include?(item.code)
49
69
  define_singleton_method(item.code){ item }
50
70
  end
51
71
  end
@@ -89,7 +109,7 @@ module StaticModels
89
109
 
90
110
  define_method("#{association}=") do |value|
91
111
  if expected_class && !value.nil? && value.class != expected_class
92
- raise TypeError.new("Expected #{expected_class} got #{value.class}")
112
+ raise ValueError.new("Expected #{expected_class} got #{value.class}")
93
113
  end
94
114
 
95
115
  if value.nil? || value.class.include?(Model)
@@ -110,6 +130,5 @@ module StaticModels
110
130
  end
111
131
  end
112
132
 
113
- class TypeError < StandardError; end
114
- class DuplicateCodes < StandardError; end
133
+ class ValueError < StandardError; end
115
134
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: static_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nubis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-24 00:00:00.000000000 Z
11
+ date: 2017-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport