model_subsets 0.0.1 → 0.0.4

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