id 0.0.12 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
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