yaks 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +158 -56
  3. data/Rakefile +1 -3
  4. data/ataru_setup.rb +72 -0
  5. data/find_missing_tests.rb +34 -0
  6. data/lib/yaks.rb +8 -10
  7. data/lib/yaks/breaking_changes.rb +4 -6
  8. data/lib/yaks/builder.rb +1 -1
  9. data/lib/yaks/changelog.rb +1 -1
  10. data/lib/yaks/collection_mapper.rb +8 -5
  11. data/lib/yaks/collection_resource.rb +0 -1
  12. data/lib/yaks/config.rb +17 -7
  13. data/lib/yaks/configurable.rb +20 -14
  14. data/lib/yaks/default_policy.rb +82 -33
  15. data/lib/yaks/format.rb +7 -3
  16. data/lib/yaks/format/collection_json.rb +4 -4
  17. data/lib/yaks/format/hal.rb +1 -2
  18. data/lib/yaks/format/halo.rb +2 -4
  19. data/lib/yaks/format/json_api.rb +46 -27
  20. data/lib/yaks/html5_forms.rb +0 -2
  21. data/lib/yaks/mapper.rb +5 -5
  22. data/lib/yaks/mapper/association.rb +7 -7
  23. data/lib/yaks/mapper/association_mapper.rb +2 -0
  24. data/lib/yaks/mapper/attribute.rb +10 -4
  25. data/lib/yaks/mapper/config.rb +2 -2
  26. data/lib/yaks/mapper/form.rb +4 -10
  27. data/lib/yaks/mapper/form/config.rb +16 -17
  28. data/lib/yaks/mapper/form/dynamic_field.rb +1 -1
  29. data/lib/yaks/mapper/form/field.rb +16 -7
  30. data/lib/yaks/mapper/form/field/option.rb +5 -4
  31. data/lib/yaks/mapper/form/fieldset.rb +1 -1
  32. data/lib/yaks/mapper/form/legend.rb +18 -0
  33. data/lib/yaks/mapper/has_many.rb +1 -0
  34. data/lib/yaks/mapper/link.rb +7 -4
  35. data/lib/yaks/null_resource.rb +4 -5
  36. data/lib/yaks/pipeline.rb +2 -2
  37. data/lib/yaks/primitivize.rb +3 -2
  38. data/lib/yaks/reader/hal.rb +12 -13
  39. data/lib/yaks/reader/json_api.rb +50 -33
  40. data/lib/yaks/resource.rb +6 -7
  41. data/lib/yaks/resource/form.rb +2 -12
  42. data/lib/yaks/resource/form/field.rb +4 -3
  43. data/lib/yaks/resource/form/field/option.rb +1 -1
  44. data/lib/yaks/resource/form/fieldset.rb +1 -1
  45. data/lib/yaks/resource/form/legend.rb +18 -0
  46. data/lib/yaks/resource/has_fields.rb +13 -7
  47. data/lib/yaks/resource/link.rb +1 -1
  48. data/lib/yaks/runner.rb +5 -2
  49. data/lib/yaks/serializer.rb +2 -3
  50. data/lib/yaks/util.rb +7 -8
  51. data/lib/yaks/version.rb +1 -1
  52. data/spec/acceptance/acceptance_spec.rb +53 -38
  53. data/spec/acceptance/json_shared_examples.rb +45 -12
  54. data/spec/acceptance/models.rb +1 -1
  55. data/spec/integration/dynamic_form_fields_spec.rb +0 -1
  56. data/spec/integration/fieldset_spec.rb +18 -20
  57. data/spec/integration/map_to_resource_spec.rb +6 -6
  58. data/spec/json/{confucius.collection.json → confucius.collection_json.json} +0 -0
  59. data/spec/json/confucius.json_api.json +43 -27
  60. data/spec/json/list_of_quotes.collection_json.json +43 -0
  61. data/spec/json/list_of_quotes.hal.json +18 -0
  62. data/spec/json/list_of_quotes.json_api.json +25 -0
  63. data/spec/json/youtypeitwepostit.collection_json.json +45 -0
  64. data/spec/spec_helper.rb +4 -3
  65. data/spec/support/classes_for_policy_testing.rb +38 -14
  66. data/spec/support/deep_eql.rb +21 -18
  67. data/spec/support/pet_mapper.rb +2 -0
  68. data/spec/support/shared_contexts.rb +9 -9
  69. data/spec/unit/yaks/builder_spec.rb +41 -18
  70. data/spec/unit/yaks/collection_mapper_spec.rb +22 -19
  71. data/spec/unit/yaks/collection_resource_spec.rb +16 -8
  72. data/spec/unit/yaks/config_spec.rb +215 -19
  73. data/spec/unit/yaks/configurable_spec.rb +66 -7
  74. data/spec/unit/yaks/default_policy/derive_mapper_from_collection_spec.rb +47 -0
  75. data/spec/unit/yaks/default_policy/derive_mapper_from_item_spec.rb +114 -0
  76. data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +29 -71
  77. data/spec/unit/yaks/default_policy_spec.rb +4 -5
  78. data/spec/unit/yaks/format/collection_json_spec.rb +35 -36
  79. data/spec/unit/yaks/format/hal_spec.rb +3 -3
  80. data/spec/unit/yaks/format/json_api_spec.rb +109 -68
  81. data/spec/unit/yaks/format_spec.rb +34 -0
  82. data/spec/unit/yaks/fp/callable_spec.rb +5 -3
  83. data/spec/unit/yaks/mapper/association_mapper_spec.rb +22 -4
  84. data/spec/unit/yaks/mapper/association_spec.rb +23 -11
  85. data/spec/unit/yaks/mapper/attribute_spec.rb +46 -7
  86. data/spec/unit/yaks/mapper/config_spec.rb +2 -3
  87. data/spec/unit/yaks/mapper/form/config_spec.rb +95 -0
  88. data/spec/unit/yaks/mapper/form/dynamic_field_spec.rb +30 -0
  89. data/spec/unit/yaks/mapper/form/field/option_spec.rb +48 -4
  90. data/spec/unit/yaks/mapper/form/field_spec.rb +43 -2
  91. data/spec/unit/yaks/mapper/form/fieldset_spec.rb +67 -8
  92. data/spec/unit/yaks/mapper/form/legend_spec.rb +52 -0
  93. data/spec/unit/yaks/mapper/form_spec.rb +84 -23
  94. data/spec/unit/yaks/mapper/has_many_spec.rb +39 -36
  95. data/spec/unit/yaks/mapper/has_one_spec.rb +28 -20
  96. data/spec/unit/yaks/mapper/link_spec.rb +68 -16
  97. data/spec/unit/yaks/mapper_spec.rb +118 -30
  98. data/spec/unit/yaks/null_resource_spec.rb +83 -52
  99. data/spec/unit/yaks/pipeline_spec.rb +101 -74
  100. data/spec/unit/yaks/primitivize_spec.rb +25 -6
  101. data/spec/unit/yaks/resource/form/field_spec.rb +5 -5
  102. data/spec/unit/yaks/resource/form/fieldset_spec.rb +7 -0
  103. data/spec/unit/yaks/resource/form/legend_spec.rb +8 -0
  104. data/spec/unit/yaks/resource/form_spec.rb +17 -37
  105. data/spec/unit/yaks/resource/has_fields_spec.rb +44 -3
  106. data/spec/unit/yaks/resource/link_spec.rb +11 -6
  107. data/spec/unit/yaks/resource_spec.rb +87 -98
  108. data/spec/unit/yaks/runner_spec.rb +112 -28
  109. data/spec/unit/yaks/serializer_spec.rb +1 -1
  110. data/spec/unit/yaks/util_spec.rb +30 -10
  111. data/spec/yaml/list_of_quotes.yaml +13 -0
  112. data/yaks.gemspec +21 -13
  113. metadata +129 -41
  114. data/lib/yaks/attributes.rb +0 -86
  115. data/lib/yaks/fp.rb +0 -26
  116. data/lib/yaks/identifier/link_relation.rb +0 -17
  117. data/resources/iana-link-relations.csv +0 -152
  118. data/spec/json/youtypeitwepostit.collection.json +0 -45
  119. data/spec/unit/yaks/attributes_spec.rb +0 -178
  120. data/spec/unit/yaks/fp_spec.rb +0 -29
@@ -1,86 +0,0 @@
1
- module Yaks
2
- class Attributes < Module
3
- attr_reader :defaults, :names
4
-
5
- def initialize(*attrs)
6
- @defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
7
- @names = (attrs + @defaults.keys).uniq
8
- end
9
-
10
- def add(*attrs)
11
- defaults = attrs.last.instance_of?(Hash) ? attrs.pop : {}
12
- self.class.new(*[*(names+attrs), @defaults.merge(defaults)])
13
- end
14
-
15
- def remove(*attrs)
16
- self.class.new(*[*(names-attrs), @defaults.reject {|k| attrs.include?(k) }])
17
- end
18
-
19
- def included(descendant)
20
- descendant.module_exec(self) do |this|
21
- include InstanceMethods,
22
- Anima.new(*this.names),
23
- Anima::Update
24
-
25
- alias with update
26
-
27
- this.names.each do |attr|
28
- define_method "with_#{attr}" do |value|
29
- with(attr => value)
30
- end
31
- end
32
-
33
- define_singleton_method(:attributes) { this }
34
- end
35
- end
36
-
37
- module InstanceMethods
38
- def initialize(attributes = {})
39
- super(self.class.attributes.defaults.merge(attributes))
40
- end
41
-
42
- def append_to(type, *objects)
43
- with(type => instance_variable_get("@#{type}") + objects)
44
- end
45
-
46
- def to_h_compact
47
- defaults = self.class.attributes.defaults
48
- to_h.reject do |attr, value|
49
- value.equal?(defaults[attr])
50
- end
51
- end
52
-
53
- def pp
54
- indent = ->(str) { str.lines.map {|l| " #{l}"}.join }
55
- format = ->(val) { val.respond_to?(:pp) ? val.pp : val.inspect }
56
-
57
- values = to_h_compact
58
-
59
- fmt_attrs = values.map do |attr, value|
60
- fmt_val = case value
61
- when Array
62
- if value.inspect.length < 50
63
- "[#{value.map(&format).join(", ")}]"
64
- else
65
- "[\n#{indent[value.map(&format).join(",\n")]}\n]"
66
- end
67
- else
68
- format[value]
69
- end
70
- "#{attr}: #{fmt_val}"
71
- end
72
-
73
- fmt_attrs_str = fmt_attrs.join(", ")
74
-
75
- if fmt_attrs_str.length > 50
76
- fmt_attrs_str = fmt_attrs.join(",\n")
77
- end
78
-
79
- if fmt_attrs_str =~ /\n/
80
- fmt_attrs_str = "\n#{indent[fmt_attrs_str]}\n"
81
- end
82
- "#{self.class.name}.new(#{fmt_attrs_str})"
83
- end
84
- end
85
- end
86
- end
data/lib/yaks/fp.rb DELETED
@@ -1,26 +0,0 @@
1
- module Yaks
2
- module FP
3
- extend self
4
-
5
- # @param [Symbol, String] name
6
- # @return [Proc]
7
- def curry_method(name)
8
- method(name).to_proc.curry
9
- end
10
-
11
-
12
- # @return [Proc]
13
- def identity_function
14
- ->(x) {x}
15
- end
16
- I = identity_function
17
-
18
- # @param [Symbol] symbol
19
- # @param [Array] args
20
- # @param [Proc] blk
21
- # @return [Proc]
22
- def send_with_args(symbol, *args, &blk)
23
- ->(obj) { obj.method(symbol).(*args, &blk) }
24
- end
25
- end
26
- end
@@ -1,17 +0,0 @@
1
- module Yaks
2
- module Identifier
3
- module LinkRelation
4
- def self.iana_registry
5
- @iana_registry ||= CSV.read(Yaks::Root.join('resources/iana-link-relations.csv'))
6
- end
7
-
8
- def self.registered_names
9
- @registered_names = iana_registry.drop(1).map(&:first)
10
- end
11
-
12
- def self.iana?(name)
13
- registered_names.include?(name.to_s)
14
- end
15
- end
16
- end
17
- end
@@ -1,152 +0,0 @@
1
- Relation Name,Description,Reference,Notes
2
- about,Refers to a resource that is the subject of the link's context.,"[RFC6903], section 2",
3
- alternate,Refers to a substitute for this context,[http://www.w3.org/TR/html5/links.html#link-type-alternate],
4
- appendix,Refers to an appendix.,[http://www.w3.org/TR/1999/REC-html401-19991224],
5
- archives,"Refers to a collection of records, documents, or other
6
- materials of historical interest.",[http://www.w3.org/TR/2011/WD-html5-20110113/links.html#rel-archives],
7
- author,Refers to the context's author.,[http://www.w3.org/TR/html5/links.html#link-type-author],
8
- bookmark,Gives a permanent link to use for bookmarking purposes.,[http://www.w3.org/TR/html5/links.html#link-type-bookmark],
9
- canonical,Designates the preferred version of a resource (the IRI and its contents).,[RFC6596],
10
- chapter,Refers to a chapter in a collection of resources.,[http://www.w3.org/TR/1999/REC-html401-19991224],
11
- collection,The target IRI points to a resource which represents the collection resource for the context IRI.,[RFC6573],
12
- contents,Refers to a table of contents.,[http://www.w3.org/TR/1999/REC-html401-19991224],
13
- copyright,"Refers to a copyright statement that applies to the
14
- link's context.",[http://www.w3.org/TR/1999/REC-html401-19991224],
15
- create-form,The target IRI points to a resource where a submission form can be obtained.,[RFC6861],
16
- current,"Refers to a resource containing the most recent
17
- item(s) in a collection of resources.",[RFC5005],
18
- describedby,"Refers to a resource providing information about the
19
- link's context.",[http://www.w3.org/TR/powder-dr/#assoc-linking],
20
- describes,"The relationship A 'describes' B asserts that
21
- resource A provides a description of resource B. There are no
22
- constraints on the format or representation of either A or B,
23
- neither are there any further constraints on either resource.",[RFC6892],"This link relation type is the inverse of the 'describedby'
24
- relation type. While 'describedby' establishes a relation from
25
- the described resource back to the resource that describes it,
26
- 'describes' established a relation from the describing resource to
27
- the resource it describes. If B is 'describedby' A, then A
28
- 'describes' B."
29
- disclosure,Refers to a list of patent disclosures made with respect to material for which 'disclosure' relation is specified.,[RFC6579],
30
- duplicate,"Refers to a resource whose available representations
31
- are byte-for-byte identical with the corresponding representations of
32
- the context IRI.",[RFC6249],"This relation is for static resources. That is, an HTTP GET
33
- request on any duplicate will return the same representation. It
34
- does not make sense for dynamic or POSTable resources and should not
35
- be used for them."
36
- edit,"Refers to a resource that can be used to edit the
37
- link's context.",[RFC5023],
38
- edit-form,"The target IRI points to a resource where a submission form for
39
- editing associated resource can be obtained.",[RFC6861],
40
- edit-media,"Refers to a resource that can be used to edit media
41
- associated with the link's context.",[RFC5023],
42
- enclosure,"Identifies a related resource that is potentially
43
- large and might require special handling.",[RFC4287],
44
- first,"An IRI that refers to the furthest preceding resource
45
- in a series of resources.",[RFC5988],"This relation type registration did not indicate a
46
- reference. Originally requested by Mark Nottingham in December
47
- 2004."
48
- glossary,Refers to a glossary of terms.,[http://www.w3.org/TR/1999/REC-html401-19991224],
49
- help,Refers to context-sensitive help.,[http://www.w3.org/TR/html5/links.html#link-type-help],
50
- hosts,"Refers to a resource hosted by the server indicated by
51
- the link context.",[RFC6690],"This relation is used in CoRE where links are retrieved as a
52
- ""/.well-known/core"" resource representation, and is the default
53
- relation type in the CoRE Link Format."
54
- hub,"Refers to a hub that enables registration for
55
- notification of updates to the context.",[http://pubsubhubbub.googlecode.com],This relation type was requested by Brett Slatkin.
56
- icon,Refers to an icon representing the link's context.,[http://www.w3.org/TR/html5/links.html#link-type-icon],
57
- index,Refers to an index.,[http://www.w3.org/TR/1999/REC-html401-19991224],
58
- item,The target IRI points to a resource that is a member of the collection represented by the context IRI.,[RFC6573],
59
- last,"An IRI that refers to the furthest following resource
60
- in a series of resources.",[RFC5988],"This relation type registration did not indicate a
61
- reference. Originally requested by Mark Nottingham in December
62
- 2004."
63
- latest-version,"Points to a resource containing the latest (e.g.,
64
- current) version of the context.",[RFC5829],
65
- license,Refers to a license associated with this context.,[RFC4946],"For implications of use in HTML, see:
66
- http://www.w3.org/TR/html5/links.html#link-type-license"
67
- lrdd,"Refers to further information about the link's context,
68
- expressed as a LRDD (""Link-based Resource Descriptor Document"")
69
- resource. See [RFC6415] for information about
70
- processing this relation type in host-meta documents. When used
71
- elsewhere, it refers to additional links and other metadata.
72
- Multiple instances indicate additional LRDD resources. LRDD
73
- resources MUST have an ""application/xrd+xml"" representation, and
74
- MAY have others.",[RFC6415],
75
- memento,"The Target IRI points to a Memento, a fixed resource that will not change state anymore.",[RFC7089],"A Memento for an Original Resource is a resource that
76
- encapsulates a prior state of the Original Resource."
77
- monitor,Refers to a resource that can be used to monitor changes in an HTTP resource.,[RFC5989],
78
- monitor-group,Refers to a resource that can be used to monitor changes in a specified group of HTTP resources.,[RFC5989],
79
- next,"Indicates that the link's context is a part of a series, and
80
- that the next in the series is the link target.",[http://www.w3.org/TR/html5/links.html#link-type-next],
81
- next-archive,Refers to the immediately following archive resource.,[RFC5005],
82
- nofollow,Indicates that the context’s original author or publisher does not endorse the link target.,[http://www.w3.org/TR/html5/links.html#link-type-nofollow],
83
- noreferrer,Indicates that no referrer information is to be leaked when following the link.,[http://www.w3.org/TR/html5/links.html#link-type-noreferrer],
84
- original,The Target IRI points to an Original Resource.,[RFC7089],"An Original Resource is a resource that exists or used to
85
- exist, and for which access to one of its prior states may be
86
- required."
87
- payment,Indicates a resource where payment is accepted.,[RFC5988],"This relation type registration did not indicate a
88
- reference. Requested by Joshua Kinberg and Robert Sayre. It is
89
- meant as a general way to facilitate acts of payment, and thus
90
- this specification makes no assumptions on the type of payment or
91
- transaction protocol. Examples may include a web page where
92
- donations are accepted or where goods and services are available
93
- for purchase. rel=""payment"" is not intended to initiate an
94
- automated transaction. In Atom documents, a link element with a
95
- rel=""payment"" attribute may exist at the feed/channel level and/or
96
- the entry/item level. For example, a rel=""payment"" link at the
97
- feed/channel level may point to a ""tip jar"" URI, whereas an entry/
98
- item containing a book review may include a rel=""payment"" link
99
- that points to the location where the book may be purchased
100
- through an online retailer."
101
- predecessor-version,"Points to a resource containing the predecessor
102
- version in the version history.",[RFC5829],
103
- prefetch,Indicates that the link target should be preemptively cached.,[http://www.w3.org/TR/html5/links.html#link-type-prefetch],
104
- prev,"Indicates that the link's context is a part of a series, and
105
- that the previous in the series is the link target.",[http://www.w3.org/TR/html5/links.html#link-type-prev],
106
- preview,Refers to a resource that provides a preview of the link's context.,"[RFC6903], section 3",
107
- previous,"Refers to the previous resource in an ordered series
108
- of resources. Synonym for ""prev"".",[http://www.w3.org/TR/1999/REC-html401-19991224],
109
- prev-archive,Refers to the immediately preceding archive resource.,[RFC5005],
110
- privacy-policy,Refers to a privacy policy associated with the link's context.,"[RFC6903], section 4",
111
- profile,"Identifying that a resource representation conforms
112
- to a certain profile, without affecting the non-profile semantics
113
- of the resource representation.",[RFC6906],"Profile URIs are primarily intended to be used as
114
- identifiers, and thus clients SHOULD NOT indiscriminately access
115
- profile URIs."
116
- related,Identifies a related resource.,[RFC4287],
117
- replies,"Identifies a resource that is a reply to the context
118
- of the link.",[RFC4685],
119
- search,"Refers to a resource that can be used to search through
120
- the link's context and related resources.",[http://www.opensearch.org/Specifications/OpenSearch/1.1],
121
- section,Refers to a section in a collection of resources.,[http://www.w3.org/TR/1999/REC-html401-19991224],
122
- self,Conveys an identifier for the link's context.,[RFC4287],
123
- service,"Indicates a URI that can be used to retrieve a
124
- service document.",[RFC5023],"When used in an Atom document, this relation type specifies
125
- Atom Publishing Protocol service documents by default. Requested
126
- by James Snell."
127
- start,"Refers to the first resource in a collection of
128
- resources.",[http://www.w3.org/TR/1999/REC-html401-19991224],
129
- stylesheet,Refers to a stylesheet.,[http://www.w3.org/TR/html5/links.html#link-type-stylesheet],
130
- subsection,"Refers to a resource serving as a subsection in a
131
- collection of resources.",[http://www.w3.org/TR/1999/REC-html401-19991224],
132
- successor-version,"Points to a resource containing the successor version
133
- in the version history.",[RFC5829],
134
- tag,"Gives a tag (identified by the given address) that applies to
135
- the current document.",[http://www.w3.org/TR/html5/links.html#link-type-tag],
136
- terms-of-service,Refers to the terms of service associated with the link's context.,"[RFC6903], section 5",
137
- timegate,The Target IRI points to a TimeGate for an Original Resource.,[RFC7089],"A TimeGate for an Original Resource is a resource that is
138
- capable of datetime negotiation to support access to prior states
139
- of the Original Resource."
140
- timemap,The Target IRI points to a TimeMap for an Original Resource.,[RFC7089],"A TimeMap for an Original Resource is a resource from which
141
- a list of URIs of Mementos of the Original Resource is available."
142
- type,Refers to a resource identifying the abstract semantic type of which the link's context is considered to be an instance.,"[RFC6903], section 6",
143
- up,"Refers to a parent document in a hierarchy of
144
- documents.",[RFC5988],"This relation type registration did not indicate a
145
- reference. Requested by Noah Slater."
146
- version-history,"Points to a resource containing the version history
147
- for the context.",[RFC5829],
148
- via,"Identifies a resource that is the source of the
149
- information in the link's context.",[RFC4287],
150
- working-copy,Points to a working copy for this resource.,[RFC5829],
151
- working-copy-of,"Points to the versioned resource from which this
152
- working copy was obtained.",[RFC5829],
@@ -1,45 +0,0 @@
1
- {
2
- "collection" :
3
- {
4
- "version" : "1.0",
5
- "href" : "http://www.youtypeitwepostit.com/api/",
6
-
7
- "items" :
8
- [
9
- {
10
- "href": "http://www.youtypeitwepostit.com/api/12091295723803341",
11
- "data": [
12
- {
13
- "name": "text",
14
- "value": "massage"
15
- },
16
- {
17
- "name": "date_posted",
18
- "value": "2014-05-29T07:56:58.035Z"
19
- }
20
- ],
21
- "links" :
22
- [
23
- { "rel": "profile", "href" : "http://www.youtypeitwepostit.com/profiles/message" }
24
- ]
25
- },
26
- {
27
- "href": "http://www.youtypeitwepostit.com/api/613856331910938",
28
- "data": [
29
- {
30
- "name": "text",
31
- "value": "Squid!"
32
- },
33
- {
34
- "name": "date_posted",
35
- "value": "2013-03-28T21:51:08.406Z"
36
- }
37
- ],
38
- "links" :
39
- [
40
- { "rel": "profile", "href" : "http://www.youtypeitwepostit.com/profiles/message" }
41
- ]
42
- }
43
- ]
44
- }
45
- }
@@ -1,178 +0,0 @@
1
- RSpec.describe Yaks::Attributes do
2
- subject { Class.new { include Yaks::Attributes.new(:foo, bar: 3) } }
3
-
4
- it 'should have a hash-based constructor' do
5
- expect(subject.new(foo: 3, bar: 4).bar).to equal 4
6
- end
7
-
8
- it 'should have defaults constructor' do
9
- expect(subject.new(foo: 3).bar).to equal 3
10
- end
11
-
12
- it 'should allow updating through with' do
13
- expect(subject.new(foo: 3).with(foo: 4).to_h).to eql(foo: 4, bar: 3)
14
- end
15
-
16
- it 'should add an #append_to method' do
17
- expect(subject.new(foo: [6]).append_to(:foo, 7, 8).foo).to eql [6, 7, 8]
18
- end
19
-
20
- context 'with all defaults' do
21
- subject { Class.new { include Yaks::Attributes.new(foo: 5, bar: 3) } }
22
-
23
- it 'should be able to construct without arguments' do
24
- expect(subject.new.to_h).to eql(foo: 5, bar: 3)
25
- end
26
- end
27
-
28
- context 'without any defaults' do
29
- subject { Class.new { include Yaks::Attributes.new(:foo, :bar) } }
30
-
31
- it 'should allow setting all attributes' do
32
- expect(subject.new(foo: 5, bar: 6).bar).to equal 6
33
- end
34
-
35
- it 'should expect all attributes' do
36
- expect { subject.new(foo: 5) }.to raise_exception
37
- end
38
- end
39
-
40
- context 'when extending' do
41
- subject { Class.new(super()) { include attributes.add(baz: 7, bar: 4) } }
42
-
43
- it 'should make the new attributes available' do
44
- expect(subject.new(foo: 3, baz: 6).baz).to equal 6
45
- end
46
-
47
- it 'should make the old attributes available' do
48
- expect(subject.new(foo: 3, baz: 6).foo).to equal 3
49
- end
50
-
51
- it 'should take new default values' do
52
- expect(subject.new(foo: 3, baz: 6).bar).to equal 4
53
- end
54
-
55
- it 'should make sure attribute names are uniq' do
56
- expect(subject.attributes.names.length).to equal 3
57
- end
58
-
59
- context 'without any defaults' do
60
- subject { Class.new(super()) { include attributes.add(:bax) } }
61
-
62
- it 'should allow setting all attributes' do
63
- expect(subject.new(foo: 5, bar: 6, bax: 7).bax).to equal 7
64
- end
65
-
66
- it 'should expect all attributes' do
67
- expect { subject.new(foo: 5, bar: 6) }.to raise_exception
68
- end
69
- end
70
- end
71
-
72
- context 'when removing an attribute with a default' do
73
- subject { Class.new(super()) { include attributes.remove(:bar) } }
74
-
75
- it 'should still recognize attributes that were kept' do
76
- expect(subject.new(foo: 2).foo).to equal 2
77
- end
78
-
79
- it 'should no longer recognize the old attributes' do
80
- expect { subject.new(foo: 3, bar: 3).bar }.to raise_error
81
- end
82
- end
83
-
84
- context 'when removing an attribute without a default' do
85
- subject { Class.new(super()) { include attributes.remove(:foo) } }
86
-
87
- it 'should still recognize attributes that were kept' do
88
- expect(subject.new(bar: 2).bar).to equal 2
89
- end
90
-
91
- it 'should no longer recognize the old attributes' do
92
- expect { subject.new(foo: 3).foo }.to raise_error
93
- end
94
-
95
- it 'should keep the defaults' do
96
- expect(subject.new.bar).to equal 3
97
- end
98
- end
99
- end
100
-
101
- RSpec.describe Yaks::Attributes::InstanceMethods do
102
- let(:widget) do
103
- Class.new do
104
- include Yaks::Attributes.new(:color, :size, options: {})
105
- def self.name ; 'Widget' ; end
106
- end
107
- end
108
-
109
- let(:widget_container) do
110
- Class.new do
111
- include Yaks::Attributes.new(widgets: [])
112
- def self.name ; 'WidgetContainer' ; end
113
- end
114
- end
115
-
116
- let(:fixed_width) do
117
- Class.new do
118
- def initialize(width)
119
- @width = width
120
- end
121
-
122
- def inspect
123
- "#" * @width
124
- end
125
- end
126
- end
127
-
128
- describe '#pp' do
129
- it 'should render correctly' do
130
- expect(widget_container.new(widgets: [
131
- widget.new(color: :green, size: 7),
132
- widget.new(color: :blue, size: 9, options: {foo: :bar})
133
- ]).pp).to eql "
134
- WidgetContainer.new(
135
- widgets: [
136
- Widget.new(color: :green, size: 7),
137
- Widget.new(color: :blue, size: 9, options: {:foo=>:bar})
138
- ]
139
- )
140
- ".strip
141
- end
142
-
143
- it 'should inline short arrays' do
144
- expect(widget_container.new(widgets: [
145
- fixed_width.new(23),
146
- fixed_width.new(22)
147
- ]).pp).to eql "WidgetContainer.new(widgets: [#######################, ######################])"
148
- end
149
-
150
- it 'should put longer arrays on multiple lines' do
151
- expect(widget_container.new(widgets: [
152
- fixed_width.new(23),
153
- fixed_width.new(23)
154
- ]).pp).to eql "WidgetContainer.new(\n widgets: [\n #######################,\n #######################\n ]\n)"
155
- end
156
-
157
- it 'should puts attributes on multiple lines if total length exceeds 50 chars' do
158
- expect(widget.new(color: fixed_width.new(18), size: fixed_width.new(18)).pp).to match /\n/
159
- expect(widget.new(color: fixed_width.new(18), size: fixed_width.new(17)).pp).to_not match /\n/
160
- end
161
- end
162
-
163
- describe '#append_to' do
164
- it 'should append to a named collection' do
165
- expect(widget_container.new(widgets: [:bar]).append_to(:widgets, :foo)).to eql widget_container.new(widgets: [:bar, :foo])
166
- end
167
- end
168
-
169
- describe '#initialize' do
170
- it 'should take hash-based args' do
171
- expect(widget_container.new(widgets: [:bar])).to eql widget_container.new.with_widgets([:bar])
172
- end
173
-
174
- it 'should use defaults when available' do
175
- expect(widget.new(color: :blue, size: 3).options).to eql({})
176
- end
177
- end
178
- end