id 0.0.12 → 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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -3
  3. data/Gemfile.lock +25 -10
  4. data/LICENSE.md +1 -1
  5. data/README.md +173 -35
  6. data/id.gemspec +8 -3
  7. data/lib/id.rb +21 -15
  8. data/lib/id/active_model.rb +30 -0
  9. data/lib/id/association.rb +26 -0
  10. data/lib/id/boolean.rb +8 -0
  11. data/lib/id/coercion.rb +38 -0
  12. data/lib/id/eta_expansion.rb +5 -0
  13. data/lib/id/field.rb +46 -0
  14. data/lib/id/field/definition.rb +44 -0
  15. data/lib/id/field/summary.rb +35 -0
  16. data/lib/id/form.rb +41 -13
  17. data/lib/id/form_backwards_compatibility.rb +6 -0
  18. data/lib/id/hashifier.rb +13 -24
  19. data/lib/id/model.rb +29 -25
  20. data/lib/id/timestamps.rb +15 -15
  21. data/lib/id/validations.rb +8 -0
  22. data/spec/examples/cat_spec.rb +37 -0
  23. data/spec/lib/id/active_model_spec.rb +40 -0
  24. data/spec/lib/id/association_spec.rb +73 -0
  25. data/spec/lib/id/boolean_spec.rb +38 -0
  26. data/spec/lib/id/coercion_spec.rb +53 -0
  27. data/spec/lib/id/eta_expansion_spec.rb +13 -0
  28. data/spec/lib/id/field/definition_spec.rb +37 -0
  29. data/spec/lib/id/field/summary_spec.rb +26 -0
  30. data/spec/lib/id/field_spec.rb +62 -0
  31. data/spec/lib/id/form_spec.rb +84 -0
  32. data/spec/lib/id/hashifier_spec.rb +19 -0
  33. data/spec/lib/id/model_spec.rb +30 -180
  34. data/spec/lib/id/timestamps_spec.rb +22 -20
  35. data/spec/lib/id/validations_spec.rb +18 -0
  36. data/spec/spec_helper.rb +11 -5
  37. data/spec/support/dummy_rails_form_builder.rb +9 -0
  38. metadata +84 -26
  39. data/lib/id/form/active_model_form.rb +0 -41
  40. data/lib/id/form/descriptor.rb +0 -27
  41. data/lib/id/form/field_form.rb +0 -14
  42. data/lib/id/form/field_with_form_support.rb +0 -12
  43. data/lib/id/missing_attribute_error.rb +0 -4
  44. data/lib/id/model/association.rb +0 -49
  45. data/lib/id/model/definer.rb +0 -23
  46. data/lib/id/model/descriptor.rb +0 -23
  47. data/lib/id/model/field.rb +0 -61
  48. data/lib/id/model/has_many.rb +0 -11
  49. data/lib/id/model/has_one.rb +0 -17
  50. data/lib/id/model/type_casts.rb +0 -96
  51. data/spec/lib/id/model/association_spec.rb +0 -27
  52. data/spec/lib/id/model/field_spec.rb +0 -0
  53. data/spec/lib/id/model/form_spec.rb +0 -56
  54. data/spec/lib/id/model/type_casts_spec.rb +0 -44
  55. data/spec/lib/mike_spec.rb +0 -20
@@ -1,41 +0,0 @@
1
- module Id
2
- module Form
3
- class ActiveModelForm
4
- include ActiveModel::Validations
5
- include ActiveModel::Conversion
6
- extend ActiveModel::Naming
7
-
8
- def self.i18n_scope
9
- :id
10
- end
11
-
12
- def initialize(model)
13
- @model = model
14
- end
15
-
16
- def persisted?
17
- false
18
- end
19
-
20
- def to_model
21
- self
22
- end
23
-
24
- def to_partial_path
25
- model.respond_to?(:to_partial_path) ? model.to_partial_path : super
26
- end
27
-
28
- private
29
-
30
- def method_missing(name, *args, &block)
31
- model.send(name, *args, &block)
32
- end
33
-
34
- def memoize(f, &b)
35
- instance_variable_get("@#{f}") || instance_variable_set("@#{f}", b.call)
36
- end
37
-
38
- attr_reader :model
39
- end
40
- end
41
- end
@@ -1,27 +0,0 @@
1
- module Id
2
- module Form
3
- module Descriptor
4
-
5
- def field(f, options={})
6
- FieldWithFormSupport.new(self, f, options).define
7
- end
8
-
9
- def form &block
10
- form_object.send :instance_exec, &block
11
- end
12
-
13
- def form_object
14
- base = self
15
- @form_object ||= Class.new(ActiveModelForm) do
16
- eingenclass = class << self
17
- self
18
- end
19
- eingenclass.send(:define_method, :model_name) do
20
- ActiveModel::Name.new(self, nil, base.name)
21
- end
22
- end
23
- end
24
-
25
- end
26
- end
27
- end
@@ -1,14 +0,0 @@
1
- class FieldForm
2
-
3
- def self.define(field)
4
- field.model.form_object.instance_eval do
5
- define_method field.name do
6
- memoize field.name do
7
- Option[model.send(field.name)].flatten.value_or nil if model.data.has_key? field.key
8
- end
9
- end
10
- attr_writer field.name
11
- end
12
- end
13
-
14
- end
@@ -1,12 +0,0 @@
1
- module Id
2
- module Form
3
- class FieldWithFormSupport < Id::Model::Field
4
-
5
- def hook_define
6
- FieldForm.define(self)
7
- end
8
-
9
- end
10
- end
11
- end
12
-
@@ -1,4 +0,0 @@
1
- module Id
2
- class MissingAttributeError < StandardError
3
- end
4
- end
@@ -1,49 +0,0 @@
1
- module Id
2
- module Model
3
- class Association < Field
4
-
5
- def type
6
- options.fetch(:type) { inferred_class }
7
- end
8
-
9
- def inferred_class
10
- hierarchy.parent.const_get(inferred_class_name)
11
- end
12
-
13
- def inferred_class_name
14
- @inferred_class_name ||= name.to_s.classify
15
- end
16
-
17
- def hierarchy
18
- @hierarchy ||= Hierarchy.new(model.name, inferred_class_name)
19
- end
20
-
21
- class Hierarchy
22
-
23
- def initialize(path, child)
24
- @path = path
25
- @child = child
26
- end
27
-
28
- def parent
29
- @parent ||= constants.find do |c|
30
- c.ancestors.find { |anc| anc.const_defined? child }
31
- end
32
- end
33
-
34
- def constants
35
- hierarchy.map(&:constantize)
36
- end
37
-
38
- private
39
-
40
- def hierarchy(name=path)
41
- name.match /(.*)::.*$/
42
- $1 ? [name] + hierarchy($1) : [name]
43
- end
44
-
45
- attr_reader :path, :child
46
- end
47
- end
48
- end
49
- end
@@ -1,23 +0,0 @@
1
- module Id
2
- module Model
3
- class Definer
4
-
5
- def self.method_memoize(context, name, &value_block)
6
- method(context, name) do |object|
7
- object.instance_eval do
8
- memoize(name, &value_block)
9
- end
10
- end
11
- end
12
-
13
- def self.method(context, name, &value_block)
14
- context.instance_eval do
15
- define_method name do
16
- value_block.call(self)
17
- end
18
- end
19
- end
20
-
21
- end
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- module Id
2
- module Model
3
- module Descriptor
4
-
5
- def field(f, options={})
6
- Field.new(self, f, options).define
7
- end
8
-
9
- def has_one(f, options={})
10
- HasOne.new(self, f, options).define
11
- end
12
-
13
- def has_many(f, options={})
14
- HasMany.new(self, f, options).define
15
- end
16
-
17
- def to_proc
18
- lambda { |data| new data }
19
- end
20
-
21
- end
22
- end
23
- end
@@ -1,61 +0,0 @@
1
- module Id
2
- module Model
3
- class Field
4
-
5
- def initialize(model, name, options)
6
- @model = model
7
- @name = name
8
- @options = options
9
- end
10
-
11
- def define
12
- Definer.method_memoize(model, name) { |data| value_of(data) }
13
- Definer.method(model, "#{name}?") { |obj| presence_of(obj.data) }
14
- hook_define
15
- end
16
-
17
- def hook_define
18
- end
19
-
20
- def value_of(data)
21
- value = data.fetch(key, &default_value)
22
- optional ? Option[value].map{ |d| cast d } : cast(value)
23
- end
24
-
25
- def presence_of(data)
26
- data.has_key?(key) && data.fetch(key)
27
- end
28
-
29
- def cast(value)
30
- TypeCasts.cast(options.fetch(:type, false), value)
31
- end
32
-
33
- def key
34
- options.fetch(:key, name).to_s
35
- end
36
-
37
- def default_value
38
- proc do
39
- if default? then default
40
- elsif !optional? then raise MissingAttributeError, key end
41
- end
42
- end
43
-
44
- def default?
45
- options.has_key?(:default)
46
- end
47
-
48
- def default
49
- options.fetch(:default)
50
- end
51
-
52
- def optional?
53
- options.fetch(:optional, false)
54
- end
55
- alias_method :optional, :optional?
56
-
57
- attr_reader :model, :name, :options
58
-
59
- end
60
- end
61
- end
@@ -1,11 +0,0 @@
1
- module Id
2
- module Model
3
- class HasMany < Association
4
-
5
- def value_of(data)
6
- data.fetch(key, []).map { |r| type.new(r) }
7
- end
8
-
9
- end
10
- end
11
- end
@@ -1,17 +0,0 @@
1
- module Id
2
- module Model
3
- class HasOne < Association
4
-
5
- def value_of(data)
6
- if optional?
7
- child = data.fetch(key, nil)
8
- child.nil? ? None : Some[type.new(child)]
9
- else
10
- child = data.fetch(key) { raise MissingAttributeError, key }
11
- type.new(child) unless child.nil?
12
- end
13
- end
14
-
15
- end
16
- end
17
- end
@@ -1,96 +0,0 @@
1
- module Id
2
- module Model
3
- module TypeCasts
4
-
5
- def self.cast(type, value)
6
- casts.fetch(type, Identity).new(value).cast
7
- end
8
-
9
- protected
10
-
11
- def self.register(cast)
12
- casts[cast.type] = cast
13
- end
14
-
15
- private
16
-
17
- def self.casts
18
- @casts ||= {}
19
- end
20
-
21
- class Cast
22
-
23
- def initialize(value)
24
- @value = value
25
- end
26
-
27
- def cast
28
- value.is_a?(type) ? value : conversion
29
- end
30
-
31
- def type
32
- self.class.type
33
- end
34
-
35
- def conversion
36
- raise NotImplementedError
37
- end
38
-
39
- private
40
-
41
- def self.type
42
- raise NotImplementedError
43
- end
44
-
45
- attr_reader :value
46
-
47
- end
48
-
49
- class Identity < Cast
50
- def cast
51
- value
52
- end
53
- end
54
-
55
- class Date < Cast
56
-
57
- def self.type
58
- ::Date
59
- end
60
-
61
- def conversion
62
- ::Date.parse value
63
- end
64
-
65
- TypeCasts.register(self)
66
- end
67
-
68
- class Time < Cast
69
-
70
- def self.type
71
- ::Time
72
- end
73
-
74
- def conversion
75
- ::Time.parse value
76
- end
77
-
78
- TypeCasts.register(self)
79
- end
80
-
81
- class Money < Cast
82
-
83
- def self.type
84
- ::Money
85
- end
86
-
87
- def conversion
88
- ::Money.new value.to_i
89
- end
90
-
91
- TypeCasts.register(self)
92
- end
93
-
94
- end
95
- end
96
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Id::Model::Association do
4
-
5
- module Foo
6
- module Bar
7
- module Baz
8
- class Quux
9
- end
10
- end
11
- end
12
- end
13
-
14
- let (:model) { stub(:name => "Foo::Bar::Baz::Quux") }
15
- let (:has_one) { Id::Model::Association.new(model, "yak", {}) }
16
-
17
- describe "hierarchy" do
18
- it "builds the class and module hierarchy for the model" do
19
- has_one.hierarchy.constants.should eq [
20
- Foo::Bar::Baz::Quux,
21
- Foo::Bar::Baz,
22
- Foo::Bar,
23
- Foo
24
- ]
25
- end
26
- end
27
- end
File without changes
@@ -1,56 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class Gerbil
4
- include Id::Model
5
- include Id::Form
6
-
7
- field :name
8
- field :paws
9
-
10
- form do
11
- validates_presence_of :name
12
- validates_length_of :name, :maximum => 4
13
- end
14
-
15
- def name_in_caps
16
- name.upcase
17
- end
18
-
19
- end
20
-
21
- module Id
22
- module Model
23
- describe Form do
24
-
25
- let (:gerbil) { Gerbil.new(:name => 'Berty') }
26
- let (:form) { gerbil.as_form }
27
-
28
- subject { gerbil.as_form }
29
-
30
- it_behaves_like "ActiveModel"
31
-
32
- it 'is delegated to by the model for errors' do
33
- gerbil.errors.should eq form.errors
34
- gerbil.valid?.should eq form.valid?
35
- end
36
-
37
- it 'responds to to_model' do
38
- subject.to_model.should eq subject
39
- end
40
-
41
- it 'has the same fields as the model' do
42
- form.name.should eq 'Berty'
43
- end
44
-
45
- it 'works with active model validations' do
46
- form.should_not be_valid
47
- form.name = 'Bert'
48
- form.should be_valid
49
- end
50
-
51
- it 'delegates to the model' do
52
- form.name_in_caps.should eq 'BERTY'
53
- end
54
- end
55
- end
56
- end