static_models 0.3.1 → 0.4.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
  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