flatter 0.2.0 → 0.2.1

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: 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.