flatter 0.2.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 543de04a22f3559983f3dd01ee360a7f78117df6
4
- data.tar.gz: 5e6e173e3c3b60d0109ddb9a898b61fcd756254f
3
+ metadata.gz: e8c9d3f37b6dfdb2b990df2a47c1682af45a526b
4
+ data.tar.gz: 83e78ea63b40fcbceea19a6f940f97747a00bd2f
5
5
  SHA512:
6
- metadata.gz: 8d818795d50e0d5a138e430ad5b1e5c3b4983e93bba7f5a34561592d92a35ca17ac57e3d340f7674f3662602e6a290fcadf7a78482f6b9fb66bdcc288d02655a
7
- data.tar.gz: 052590d63bd471a285e3268497189bf14185d9bd24b1a69058a363b550f4370c590239abe7277d29f91247a20b180146ab34bf3264be689897ad1b7bfca71687
6
+ metadata.gz: bed580ee036c3d9a21ce0c24e293e4472f0664ae6d4f8acbd93cb8a2cbdf8018cf5e5a3e4b5a873e1a7c8cd799ae2a3c100c5bd865792e8141e44c37f063a830
7
+ data.tar.gz: 8463c12d806db30ad17305ceaaf3b9493e65b9074fff674e21e5b2a3fcfc22f3427d6bfc8f7f73991dbe81fa3cfc96e65806d6b387a3156dbcfd0ef6b86b46f9
data/README.md CHANGED
@@ -79,15 +79,15 @@ end
79
79
  #### Mapping Options
80
80
 
81
81
  - `:reader` Allows to add a custom logic for reading target's attribute.
82
- When value is `String` or `Symbol`, calls a method defined by a **mapper** class.
82
+ When value is `Symbol`, calls a method defined by a **mapper** class.
83
83
  If that method accepts an argument, mapping name will be passed to it.
84
84
  When value is `Proc`, it is executed in context of mapper object, yielding
85
- mapping name if block has arity of 1. For other arbitrary objects will simply
86
- return that object.
85
+ mapping name if block has arity of 1. For other arbitrary objects (including
86
+ `String`s) will simply return that object.
87
87
 
88
88
  - `:writer` Allows to control a way how value is assigned (written).
89
- When value is `String` or `Symbol`, calls a method defined by a **mapper** class,
90
- passing a value to it. If that method accepts second argument, mapping name will be
89
+ When value is `Symbol`, calls a method defined by a **mapper** class, passing
90
+ a value to it. If that method accepts second argument, mapping name will be
91
91
  additionally passed to it.
92
92
  When value is `Proc`, it is executed in context of mapper object, yielding
93
93
  value and optionally mapping name if block has arity of 2. For other values will
@@ -518,14 +518,14 @@ class DepartmentMapper < Flatter::Mapper
518
518
  end
519
519
  ```
520
520
 
521
- `mapper.first_name` no longer able to return specific value, since it's
521
+ `department_mapper.first_name` no longer able to return specific value, since it's
522
522
  not clear which first name should it be. Thus, when mapper is mounted as
523
523
  a collection item, instead of singular value accessors you gain pluralized
524
524
  reader methods:
525
525
 
526
526
  ```ruby
527
527
  # all first_names of all people of the mapped department:
528
- mapper.first_names # => ["John", "Derek"]
528
+ department_mapper.first_names # => ["John", "Derek"]
529
529
  ```
530
530
 
531
531
  The same concerns for all nested (singular or collection) mappings and mountings
@@ -533,15 +533,15 @@ under collection mapper:
533
533
 
534
534
  ```ruby
535
535
  # all phone number of all people of the mapped department
536
- mapper.phone_numbers # => ["111-222-3333", "222-111-33333"]
536
+ department_mapper.phone_numbers # => ["111-222-3333", "222-111-33333"]
537
537
 
538
538
  # all the people
539
- mapper.people # =>
539
+ department_mapper.people # =>
540
540
  # [{"first_name" => "John", "last_name" => "Smith", "key" => 1, "phone_number" => "111-222-3333"},
541
541
  # {"first_name" => "Derek", "last_name" => "Parker", "key" => 2, "phone_number" => "222-111-3333"}]
542
542
 
543
543
  # all phones (note the :phone mapper mounted on :people, opposed to it's :phone_number mapping)
544
- mapper.phones # =>
544
+ department_mapper.phones # =>
545
545
  # [{"phone_number" => "111-222-3333"}, {"phone_number" => "222-111-33333"}]
546
546
  ```
547
547
 
@@ -68,18 +68,24 @@ module Flatter
68
68
 
69
69
  def add_item(params)
70
70
  collection << clone.tap do |mapper|
71
- item = target_class.new
71
+ item = build_collection_item
72
72
  mapper.reset_locals!
73
73
  mapper.set_target!(item)
74
74
  mapper.item_index = collection.length
75
75
  mapper.write(params)
76
- add_target_item(item)
76
+ add_item_to_target(item)
77
77
  end
78
78
  end
79
79
 
80
- def add_target_item(item)
80
+ def build_collection_item
81
+ target_class.new
82
+ end
83
+ private :build_collection_item
84
+
85
+ def add_item_to_target(item)
81
86
  target << item
82
87
  end
88
+ private :add_item_to_target
83
89
  end
84
90
 
85
91
  def read
@@ -96,7 +102,8 @@ module Flatter
96
102
  return super unless collection?
97
103
  return unless params.key?(name)
98
104
 
99
- data = params[name]
105
+ data = extract_data(params)
106
+
100
107
  assert_collection!(data)
101
108
 
102
109
  keys = collection.map(&:key)
@@ -111,6 +118,11 @@ module Flatter
111
118
  end
112
119
  end
113
120
 
121
+ def extract_data(params)
122
+ params[name]
123
+ end
124
+ private :extract_data
125
+
114
126
  def pluralize!
115
127
  @_pluralized = true
116
128
  end
@@ -15,9 +15,16 @@ module Flatter
15
15
  end
16
16
 
17
17
  def mapper_class
18
- options[:mapper_class] || mapper_class_name.constantize
18
+ options[:mapper_class] || default_mapper_class
19
19
  end
20
20
 
21
+ def default_mapper_class
22
+ mapper_class_name.constantize
23
+ rescue NameError => e
24
+ Flatter.default_mapper_class or raise e
25
+ end
26
+ private :default_mapper_class
27
+
21
28
  def mapper_class_name
22
29
  options[:mapper_class_name] || modulize(default_mapper_class_name)
23
30
  end
@@ -1,8 +1,7 @@
1
1
  module Flatter
2
2
  module Mapper::ModelName
3
3
  def model_name
4
- target.class.respond_to?(:model_name) ?
5
- target.class.model_name : super
4
+ target.class.try(:model_name) || super
6
5
  end
7
6
  end
8
7
  end
@@ -60,6 +60,10 @@ module Flatter
60
60
  @_inner_mountings = nil
61
61
  end
62
62
 
63
+ def root
64
+ mounter.nil? ? self : mounter.root
65
+ end
66
+
63
67
  def local_mountings
64
68
  class_mountings_for(self.class)
65
69
  end
@@ -27,20 +27,18 @@ module Flatter
27
27
  super.tap{ |f| f.extension = block }
28
28
  end
29
29
 
30
- def trait(name, label = nil, &block)
31
- trait_name = "#{name}_trait"
30
+ def trait(trait_name, label: name, includes: nil, &block)
31
+ trait_name = "#{trait_name}_trait"
32
32
  mapper_class = Class.new(Flatter::Mapper)
33
- mapper_class.label = self.name || label
34
- mapper_class.class_eval(&block)
33
+ mapper_class.label = label
34
+ mapper_class.class_eval(&block) if block.present?
35
35
 
36
36
  if self.name.present?
37
37
  mapper_class_name = trait_name.camelize
38
38
  const_set(mapper_class_name, mapper_class)
39
-
40
- mount trait_name, mapper_class_name: "#{self.name}::#{mapper_class_name}", trait: true
41
- else
42
- mount trait_name, mapper_class: mapper_class, trait: true
43
39
  end
40
+
41
+ mount trait_name, mapper_class: mapper_class, trait: true, includes: includes
44
42
  end
45
43
  end
46
44
 
@@ -52,7 +50,7 @@ module Flatter
52
50
  end
53
51
 
54
52
  def extend_with(extension)
55
- singleton_class.trait :extension, self.class.name, &extension
53
+ singleton_class.trait :extension, label: self.class.name, &extension
56
54
  end
57
55
 
58
56
  def full_name
@@ -95,12 +93,40 @@ module Flatter
95
93
  end
96
94
 
97
95
  def trait_names
98
- traits.map{ |trait| "#{trait.to_s}_trait" }
96
+ traits.map{ |trait| trait_name_for(trait) }
99
97
  end
100
98
 
101
99
  def set_traits(traits)
102
- @traits = traits
100
+ @traits = resolve_trait_dependencies(traits)
101
+ end
102
+
103
+ def trait_name_for(trait)
104
+ "#{trait.to_s}_trait"
105
+ end
106
+ private :trait_name_for
107
+
108
+ def resolve_trait_dependencies(traits)
109
+ factories = self.class.mountings.values.select(&:trait?)
110
+ catch(:done){ loop{ include_traits_from!(traits, factories) } }
111
+ traits
103
112
  end
113
+ private :resolve_trait_dependencies
114
+
115
+ def include_traits_from!(traits, factories)
116
+ initial_length = traits.length
117
+ traits.map! do |trait|
118
+ factory = factories.find{ |f| f.name == trait_name_for(trait) }
119
+ if factory.present?
120
+ factories.delete(factory)
121
+ Array(factory.options[:includes]).push(trait)
122
+ else
123
+ trait
124
+ end
125
+ end
126
+ traits.flatten!
127
+ throw :done if traits.length == initial_length
128
+ end
129
+ private :include_traits_from!
104
130
 
105
131
  def trait?
106
132
  !!@trait
@@ -121,7 +147,7 @@ module Flatter
121
147
  private :trait_mountings
122
148
 
123
149
  def shared_methods
124
- self.class.public_instance_methods(false)
150
+ self.class.public_instance_methods(false) + self.class.protected_instance_methods(false)
125
151
  end
126
152
 
127
153
  def respond_to_missing?(name, *)
@@ -132,6 +158,10 @@ module Flatter
132
158
  end
133
159
  end
134
160
 
161
+ def mounter!
162
+ trait? ? mounter.mounter : mounter
163
+ end
164
+
135
165
  def method_missing(name, *args, &block)
136
166
  if trait?
137
167
  mounter.send(name, *args, &block)
@@ -11,7 +11,7 @@ module Flatter
11
11
  return super unless reader?
12
12
 
13
13
  case reader
14
- when Proc, String, Symbol
14
+ when Proc, Symbol
15
15
  args = Array((name if arity_of(reader) == 1))
16
16
  exec_or_send(reader, args)
17
17
  when false then nil
@@ -23,11 +23,11 @@ module Flatter
23
23
  return super unless writer?
24
24
 
25
25
  case writer
26
- when Proc, String, Symbol
26
+ when Proc, Symbol
27
27
  args = [value].tap{ |a| a << name if arity_of(writer) == 2 }
28
28
  exec_or_send(writer, args)
29
29
  when false then nil
30
- else fail BadWriterError, "cannot use #{writer} for assigning values"
30
+ else fail BadWriterError, "cannot use #{writer.inspect} for assigning values"
31
31
  end
32
32
  end
33
33
 
@@ -1,3 +1,3 @@
1
1
  module Flatter
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/flatter.rb CHANGED
@@ -13,7 +13,18 @@ module Flatter
13
13
 
14
14
  use :scribe, require: 'flatter/mapping/scribe'
15
15
 
16
+ mattr_accessor :default_mapper_class
17
+
16
18
  def self.configure
17
19
  yield self
18
20
  end
21
+
22
+ def self.extends(klass, *modules)
23
+ if block_given?
24
+ _module = Module.new(&Proc.new)
25
+ klass.const_set("FlatterExtension", _module)
26
+ modules.push _module
27
+ end
28
+ modules.each{ |mod| klass.send(:include, mod) }
29
+ end
19
30
  end
metadata CHANGED
@@ -1,139 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Kuzko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-25 00:00:00.000000000 Z
11
+ date: 2016-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.10'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.10'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '10.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '10.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-its
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0.9'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.9'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: pry
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: pry-nav
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  description: |-
@@ -148,9 +148,9 @@ executables:
148
148
  extensions: []
149
149
  extra_rdoc_files: []
150
150
  files:
151
- - .gitignore
152
- - .rspec
153
- - .travis.yml
151
+ - ".gitignore"
152
+ - ".rspec"
153
+ - ".travis.yml"
154
154
  - Gemfile
155
155
  - LICENSE.txt
156
156
  - README.md
@@ -191,17 +191,17 @@ require_paths:
191
191
  - lib
192
192
  required_ruby_version: !ruby/object:Gem::Requirement
193
193
  requirements:
194
- - - '>='
194
+ - - ">="
195
195
  - !ruby/object:Gem::Version
196
196
  version: 2.0.0
197
197
  required_rubygems_version: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - '>='
199
+ - - ">="
200
200
  - !ruby/object:Gem::Version
201
201
  version: '0'
202
202
  requirements: []
203
203
  rubyforge_project:
204
- rubygems_version: 2.1.11
204
+ rubygems_version: 2.5.1
205
205
  signing_key:
206
206
  specification_version: 4
207
207
  summary: Maps a deeply nested model graph to a single object with a flat set of attributes.