model_subsets 0.0.1 → 0.0.4

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.
data/lib/model_subsets.rb CHANGED
@@ -2,148 +2,259 @@ require "model_subsets/version"
2
2
 
3
3
  module ModelSubsets
4
4
 
5
- # Includes class methods
6
- def self.included(base)
7
- base.extend ModelSubsets::ClassMethods
8
- end
5
+ extend ActiveSupport::Concern
9
6
 
10
- # Provides current subset fieldset list
11
- def fieldset
12
- self.class.subset_fieldset(self.subset)
13
- end
7
+ # Return current subset fieldsets list
8
+ #
9
+ # @return [ Array ]
10
+ #
11
+ # @since 0.0.2
12
+ def fieldsets
13
+ subset_content[:fieldsets] if valid_subset?
14
+ end
14
15
 
15
- # Whether a field is included in subset fieldset
16
- def has_field? field
17
- fieldset.include? field
18
- end
16
+ # Whether subset includes a fieldset
17
+ #
18
+ # @example Check if a user has fieldset :common
19
+ # user.has_fieldset? :common
20
+ #
21
+ # @param [ Symbol ] name The fieldset name
22
+ #
23
+ # @return [ Boolean ]
24
+ #
25
+ # @since 0.0.2
26
+ def has_fieldset? name
27
+ fieldsets.include?(name) if valid_subset?
28
+ end
19
29
 
20
- # Whether subset has a fieldset
21
- def has_fieldset? fieldset
22
- return unless self.class.subsets.has_key? self.subset
23
- self.class.subsets[self.subset][:fieldsets].include? fieldset
24
- end
30
+ # Whether subset is included in a subsets scope
31
+ #
32
+ # @example Check if current subset is in :users subsets scope
33
+ # person.in_subset_scope? :users
34
+ #
35
+ # @param [ Symbol ] name The subsets scope name
36
+ #
37
+ # @return [ Boolean ]
38
+ #
39
+ # @since 0.0.4
40
+ def in_subsets_scope? name
41
+ self.class.subsets_scope(name).include? subset.to_sym
42
+ end
43
+
44
+ # Returns current subset content
45
+ # An empty Hash is returned if subset is not defined
46
+ #
47
+ # @return [ Hash ]
48
+ #
49
+ # @since 0.0.2
50
+ def subset_content
51
+ self.class.subsets[subset.to_sym] if valid_subset?
52
+ end
53
+
54
+ # Whether a subset fieldset includes a field
55
+ # It only checks if the field is included in current subset fieldsets, not if the field is a column in the model
56
+ #
57
+ # @example Check if a user uses field :name
58
+ # user.has_field? :name
59
+ #
60
+ # @param [ Symbol ] name The field name
61
+ #
62
+ # @return [ Boolean ]
63
+ #
64
+ # @since 0.0.2
65
+ def subset_field? name
66
+ subset_fields.include?(name) if subset_fields
67
+ end
68
+
69
+ # Return current subset fields list
70
+ #
71
+ # @return [ Array ]
72
+ #
73
+ # @since 0.0.2
74
+ def subset_fields
75
+ self.class.subset_fields(subset.to_sym) if valid_subset?
76
+ end
25
77
 
26
- def valid_subset?
27
- return true if self.class.subsets.keys.include? self.subset
28
- errors.add(:subset, :invalid) if self.respond_to? errors
29
- return false
78
+ # Whether current subset id is defined
79
+ #
80
+ # @example Use valid_subset? as a model validation
81
+ # validate :valid_subset?
82
+ #
83
+ # @return [ Boolean ]
84
+ #
85
+ # @since 0.0.2
86
+ def valid_subset?
87
+ return true if self.class.subsets.keys.include?(subset.to_s.to_sym)
88
+ errors.add(:subset, :invalid) if respond_to?(:errors)
89
+ false
90
+ end
91
+
92
+ module ClassMethods
93
+
94
+ # Defines a fieldset
95
+ #
96
+ # @example Define fieldset :login including fields :username and :password
97
+ # fieldset :login, :username, :password
98
+ #
99
+ # @param [ Symbol ] name The fieldset name
100
+ # @param [ Array ] *args Fields names
101
+ #
102
+ # @since 0.0.2
103
+ def fieldset name, *args
104
+ @fieldsets ||= {}
105
+ @fieldsets[name] = args
30
106
  end
107
+
108
+ # Defines a subset
109
+ # If no fieldset is included, all defined fieldsets will be included by default
110
+ # If fieldsets are defined on an extended subset, parents fieldsets will be ignored
111
+ #
112
+ # @example Define subset :user, which is a person able to login
113
+ # subset :user, extends: :person, with: :login, scopes: :users
114
+ #
115
+ # @param [ Symbol ] name The subset name
116
+ # @param [ Hash ] options The options to pass to the subset
117
+ #
118
+ # @option options [ Boolean ] :template Whether subset is a template (only used as an extend)
119
+ # @option options [ Symbol ] :group Subset group name
120
+ # @option options [ Symbol, Array ] :fieldsets Explicit fieldsets list. Overrides default list (all or herited)
121
+ # @option options [ Symbol, Array ] :scopes The scopes in which subset will be included
122
+ # @option options [ Symbol, Array ] :extends Parent subsets
123
+ # @option options [ Symbol, Array ] :with Fieldsets to be added to herited fieldsets
124
+ # @option options [ Symbol, Array ] :only Filters fieldsets to remove fielsets not being in this list
125
+ # @option options [ Symbol, Array ] :except Filters fieldsets to remove fieldsets being in this list
126
+ #
127
+ # @since 0.0.2
128
+ def subset name, options = {}
129
+ @subsets ||= {}
130
+ @subsets_scopes ||= {}
131
+
132
+ options[:fieldsets] = [options[:fieldsets]] unless options[:fieldsets].blank? || options[:fieldsets].is_a?(Array)
31
133
 
32
- module ClassMethods
134
+ # Subset is an extension
135
+ if options[:extends]
33
136
 
34
- def fieldset *args
35
- fieldset = args.shift
36
- raise "fieldset id must be a Symbol (#{fieldset.class} given)" unless fieldset.is_a? Symbol
37
- raise "fieldset fields must be an Array (#{args.class} given)" unless args.is_a? Array
38
- args.each do |field|
39
- raise "field name must be an Symbol (#{field.class} given)" unless field.is_a? Symbol
137
+ # Force extends option to Array
138
+ options[:extends] = [options[:extends]] unless options[:extends].is_a?(Array)
139
+ options[:extends].each do |source_subset|
140
+ next unless @subsets.has_key? source_subset
141
+ source_options = @subsets[source_subset].clone
142
+ source_options.delete :template
143
+ options = source_options.merge options
40
144
  end
41
- @fieldsets ||= {}
42
- @fieldsets[fieldset] = args
43
- end
44
145
 
45
- # Provides subset fieldset list
46
- def subset_fieldset subset
47
- return unless subsets.has_key? subset
48
- subset_fields = []
49
- subsets[subset][:fieldsets].each do |fieldset|
50
- fieldset = @fieldsets[fieldset].is_a?(Array) ? @fieldsets[fieldset] : [@fieldsets[fieldset]]
51
- subset_fields |= fieldset
146
+ # Handle additional fieldsets list
147
+ if options[:with]
148
+ options[:with] = [options[:with]] unless options[:with].is_a?(Array)
149
+ options[:fieldsets] |= options[:with]
52
150
  end
53
- subset_fields.uniq
151
+
152
+ # Include all fieldsets by default
153
+ elsif options[:fieldsets].blank?
154
+ options[:fieldsets] = @fieldsets.keys
54
155
  end
55
156
 
56
- def subset subset, options = {}
57
- raise "subset id must be a Symbol (#{subset.class} given)" unless subset.is_a? Symbol
58
- raise "subset options must be a Hash (#{options.class} given)" unless options.is_a? Hash
59
- @subsets_config ||= {}
60
- @subsets_config[subset] = options
157
+ # Handle inclusion list
158
+ if options[:only]
159
+ options[:only] = [options[:only]] unless options[:only].is_a?(Array)
160
+ options[:fieldsets] &= options[:only]
61
161
  end
62
162
 
63
- # Provides subsets with builded extends & fieldsets
64
- def subsets options = {}
65
- @subsets_config ||= {}
66
- raise "subsets config must ba a Hash (#{@subsets_config.class} given)" unless @subsets_config.is_a? Hash
67
-
68
- # Cache builded subsets
69
- return @subsets unless @subsets.blank? || options[:purge]
70
-
71
- @subsets = {}
72
-
73
- @subsets_config.each do |subset, options|
74
- # Can't define same subset twice
75
- raise "subset '#{subset} is already defined" if @subsets.has_key? subset
76
-
77
- # Subset is an extension
78
- if options[:extends]
79
-
80
- # Force extends option to Array
81
- options[:extends] = [options[:extends]] unless options[:extends].is_a? Array
82
- options[:extends].each do |source_subset|
83
- next unless @subsets.has_key? source_subset
84
- source_options = @subsets[source_subset].clone
85
- source_options.delete :abstract
86
- options = source_options.merge options
87
- end
88
-
89
- # Handle additional fieldsets list
90
- if options[:with]
91
- options[:with] = [options[:with]] unless options[:with].is_a? Array
92
- options[:fieldsets] |= options[:with]
93
- end
94
-
95
- else
96
- # Include all fieldsets by default
97
- options[:fieldsets] = @fieldsets.keys
98
- end
99
-
100
- # Handle inclusion list
101
- if options[:only]
102
- options[:only] = [options[:only]] unless options[:only].is_a? Array
103
- options[:fieldsets] &= options[:only]
104
- end
105
-
106
- # Handle exclusion list
107
- if options[:except]
108
- options[:except] = [options[:except]] unless options[:except].is_a? Array
109
- options[:fieldsets] -= options[:except]
110
- end
111
-
112
- # Cleanup
113
- options[:fieldsets] = options[:fieldsets].uniq & @fieldsets.keys
114
- remove_options = [:extends, :with, :only, :except]
115
- options = options.clone
116
- options.delete_if{ |key, value| remove_options.include?(key) }
117
- @subsets[subset] = options
118
- end
163
+ # Handle exclusion list
164
+ if options[:except]
165
+ options[:except] = [options[:except]] unless options[:except].is_a?(Array)
166
+ options[:fieldsets] -= options[:except]
167
+ end
119
168
 
120
- @subsets = @subsets.reject{|key, value| value[:abstract] == true}
169
+ # Handle scopes
170
+ options[:scopes] ||= []
171
+ options[:scopes] = [options[:scopes]] unless options[:scopes].is_a?(Array)
172
+ options[:scopes].each do |subset_scope|
173
+ @subsets_scopes[subset_scope] ||= []
174
+ @subsets_scopes[subset_scope] << name unless options[:template]
175
+ scope subset_scope, where(:subset.in => @subsets_scopes[subset_scope])
121
176
  end
122
177
 
123
- # Provides subsets groups list formatted for use with grouped collection select
124
- def subsets_groups
125
- groups = {}
126
- i18n_group = {}
178
+ # Cleanup
179
+ options[:fieldsets] = options[:fieldsets].uniq & @fieldsets.keys
180
+ remove_options = [:extends, :with, :only, :except]
181
+ options = options.clone
182
+ options.delete_if{ |key, value| remove_options.include?(key) }
127
183
 
128
- subsets.each do |subset, options|
129
- raise "subset id must be a Symbol (#{subset.class} given)" unless subset.is_a? Symbol
184
+ # Register subset
185
+ @subsets[name] = options
186
+ end
130
187
 
131
- # Set default group
132
- options[:group] = :default unless options[:group]
188
+ # Return subset fields list
189
+ #
190
+ # @example Get fields included in subset :user of model Person
191
+ # Person.subset_fields :user
192
+ # => [ :name, :givenname, :username, :password ]
193
+ #
194
+ # @params [ Symbol ] name The subset name
195
+ #
196
+ # @returns [ Array ]
197
+ #
198
+ # @since 0.0.1
199
+ def subset_fields name
200
+ return unless subsets.has_key?(name) && subsets[name].has_key?(:fieldsets)
201
+ subset_fields = []
202
+ subsets[name][:fieldsets].each do |fieldset|
203
+ fieldset = @fieldsets[fieldset].is_a?(Array) ? @fieldsets[fieldset] : [@fieldsets[fieldset]]
204
+ subset_fields |= fieldset
205
+ end
206
+ subset_fields.uniq
207
+ end
133
208
 
134
- raise "group id must be a Symbol (#{options[:group].class} given)" unless options[:group].is_a? Symbol
209
+ # Return builded subsets
210
+ #
211
+ # @return [ Hash ]
212
+ #
213
+ # @since 0.0.1
214
+ def subsets
215
+ @subsets.reject{ |name, options| options[:template] }
216
+ end
135
217
 
136
- i18n_subset = self.human_attribute_name("subsets.#{subset}")
137
- i18n_group[options[:group]] ||= self.human_attribute_name("subsets.#{options[:group]}")
138
- groups[i18n_group[options[:group]]] ||= [options[:group], {}]
139
- groups[i18n_group[options[:group]]].last[i18n_subset] = subset
140
- end
218
+ # Provides grouped subsets list, formatted for use with grouped collection select
219
+ #
220
+ # @return [ Array ]
221
+ #
222
+ # @since 0.0.1
223
+ def subsets_groups
224
+ groups = {}
225
+ i18n_group = {}
141
226
 
142
- # Rearrange groups
143
- groups = groups.sort
144
- groups.map do |group|
145
- [group.last.first, group.first, group.last.last.sort]
146
- end
227
+ subsets.each do |subset, options|
228
+ options[:group] = :default unless options[:group]
229
+ i18n_subset = self.human_attribute_name("subsets.#{subset}")
230
+ i18n_group[options[:group]] ||= self.human_attribute_name("subsets.#{options[:group]}")
231
+ groups[i18n_group[options[:group]]] ||= [options[:group], {}]
232
+ groups[i18n_group[options[:group]]].last[i18n_subset] = subset
147
233
  end
234
+
235
+ # Rearrange groups
236
+ groups = groups.sort
237
+ groups.map do |group|
238
+ [group.last.first, group.first, group.last.last.sort]
239
+ end
240
+ end
241
+
242
+ # Return subsets included of a subsets scope
243
+ #
244
+ # @return [ Array ]
245
+ #
246
+ # @since 0.0.2
247
+ def subsets_scope name
248
+ subsets_scopes[name]
249
+ end
250
+
251
+ # Return subsets scopes list
252
+ #
253
+ # @return [ Array ]
254
+ #
255
+ # @since 0.0.2
256
+ def subsets_scopes
257
+ @subsets_scopes
148
258
  end
259
+ end
149
260
  end
@@ -0,0 +1,130 @@
1
+ module ModelSubsets
2
+ module ClassMethods
3
+
4
+ # Creates a fieldset
5
+ def fieldset *args
6
+ fieldset = args.shift
7
+ raise "fieldset id must be a Symbol (#{fieldset.class} given)" unless fieldset.is_a? Symbol
8
+ raise "fieldset fields must be an Array (#{args.class} given)" unless args.is_a? Array
9
+ args.each do |field|
10
+ raise "field name must be an Symbol (#{field.class} given)" unless field.is_a? Symbol
11
+ end
12
+ @fieldsets ||= {}
13
+ @fieldsets[fieldset] = args
14
+ end
15
+
16
+ # Creates a subset
17
+ def subset subset, options = {}
18
+ raise "subset id must be a Symbol (#{subset.class} given)" unless subset.is_a? Symbol
19
+ raise "subset options must be a Hash (#{options.class} given)" unless options.is_a? Hash
20
+ @subsets_config ||= {}
21
+ @subsets_config[subset] = options
22
+ end
23
+
24
+ # Provides subset fieldset list
25
+ def subset_fieldset subset
26
+ return unless subsets.has_key?(subset) && subsets[subset].has_key?(:fieldsets)
27
+ subset_fields = []
28
+ subsets[subset][:fieldsets].each do |fieldset|
29
+ fieldset = @fieldsets[fieldset].is_a?(Array) ? @fieldsets[fieldset] : [@fieldsets[fieldset]]
30
+ subset_fields |= fieldset
31
+ end
32
+ subset_fields.uniq
33
+ end
34
+
35
+ # Provides subsets with builded extends & fieldsets
36
+ def subsets options = {}
37
+ @subsets_config ||= {}
38
+ raise "subsets config must ba a Hash (#{@subsets_config.class} given)" unless @subsets_config.is_a? Hash
39
+
40
+ # Cache builded subsets
41
+ return @subsets unless @subsets.blank? || options[:purge]
42
+
43
+ @subsets = {}
44
+ @scopes = {}
45
+
46
+ @subsets_config.each do |subset, options|
47
+ # Can't define same subset twice
48
+ raise "subset '#{subset} is already defined" if @subsets.has_key? subset
49
+
50
+ # Subset is an extension
51
+ if options[:extends]
52
+
53
+ # Force extends option to Array
54
+ options[:extends] = [options[:extends]] unless options[:extends].is_a? Array
55
+ options[:extends].each do |source_subset|
56
+ next unless @subsets.has_key? source_subset
57
+ source_options = @subsets[source_subset].clone
58
+ source_options.delete :abstract
59
+ options = source_options.merge options
60
+ end
61
+
62
+ # Handle additional fieldsets list
63
+ if options[:with]
64
+ options[:with] = [options[:with]] unless options[:with].is_a? Array
65
+ options[:fieldsets] |= options[:with]
66
+ end
67
+
68
+ else
69
+ # Include all fieldsets by default
70
+ options[:fieldsets] = @fieldsets.keys unless options[:fieldsets].is_a? Array
71
+ end
72
+
73
+ # Handle inclusion list
74
+ if options[:only]
75
+ options[:only] = [options[:only]] unless options[:only].is_a? Array
76
+ options[:fieldsets] &= options[:only]
77
+ end
78
+
79
+ # Handle exclusion list
80
+ if options[:except]
81
+ options[:except] = [options[:except]] unless options[:except].is_a? Array
82
+ options[:fieldsets] -= options[:except]
83
+ end
84
+
85
+ # Handle scopes
86
+ options[:scopes] = [options[:scopes]] unless options[:scopes].is_a? Array
87
+ options[:scopes].each do |scope|
88
+ @scopes[scope] ||= []
89
+ @scopes[scope] << subset
90
+ end
91
+
92
+ # Cleanup
93
+ options[:fieldsets] = options[:fieldsets].uniq & @fieldsets.keys
94
+ remove_options = [:extends, :with, :only, :except]
95
+ options = options.clone
96
+ options.delete_if{ |key, value| remove_options.include?(key) }
97
+ @subsets[subset] = options
98
+ end
99
+
100
+ @subsets = @subsets.reject{|key, value| value[:abstract] == true}
101
+ end
102
+
103
+ # Provides subsets groups list formatted for use with grouped collection select
104
+ def subsets_groups
105
+ groups = {}
106
+ i18n_group = {}
107
+
108
+ subsets.each do |subset, options|
109
+ raise "subset id must be a Symbol (#{subset.class} given)" unless subset.is_a? Symbol
110
+
111
+ # Set default group
112
+ options[:group] = :default unless options[:group]
113
+
114
+ raise "group id must be a Symbol (#{options[:group].class} given)" unless options[:group].is_a? Symbol
115
+
116
+ i18n_subset = self.human_attribute_name("subsets.#{subset}")
117
+ i18n_group[options[:group]] ||= self.human_attribute_name("subsets.#{options[:group]}")
118
+ groups[i18n_group[options[:group]]] ||= [options[:group], {}]
119
+ groups[i18n_group[options[:group]]].last[i18n_subset] = subset
120
+ end
121
+
122
+ # Rearrange groups
123
+ groups = groups.sort
124
+ groups.map do |group|
125
+ [group.last.first, group.first, group.last.last.sort]
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -1,3 +1,3 @@
1
1
  module ModelSubsets
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -14,4 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "model_subsets"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = ModelSubsets::VERSION
17
+
18
+ gem.add_dependency("activemodel", ["~> 3.1"])
19
+
17
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: model_subsets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-20 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2012-07-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activemodel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.1'
14
30
  description: ModelSubsets provides ability to split a single model into fields and
15
31
  properties subsets
16
32
  email:
@@ -25,6 +41,7 @@ files:
25
41
  - README.md
26
42
  - Rakefile
27
43
  - lib/model_subsets.rb
44
+ - lib/model_subsets/class_methods.rb
28
45
  - lib/model_subsets/version.rb
29
46
  - model_subsets.gemspec
30
47
  homepage: https://github.com/porecreat/model_subets