acts_as_label 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ .DS_Store
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Coroutine LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ = acts_as_label
2
+
3
+
4
+ == Description
5
+
6
+ This acts_as extension implements a system label and a friendly label on a class and centralizes
7
+ the logic for performing validations and accessing items by system label.
8
+
9
+
10
+
11
+ == Usage
12
+
13
+ If you just want validations and system label accessors, simply add acts_as_label to the model.
14
+
15
+ class Role < ActiveRecord::Base
16
+ acts_as_label
17
+ end
18
+
19
+
20
+ The plugin accepts three optional parameters.
21
+
22
+ +system_label_column+:: specifies the name of the column to use for the system label (default: system_label)
23
+ +label_column+:: specifies the name of the column to use for the label (default: label)
24
+ +default+:: specifies the system label value to use as the default record
25
+
26
+ class Role < ActiveRecord::Base
27
+ acts_as_label :system_label_column => :key, :label_column => :name, :default => :guest
28
+ end
29
+
30
+
31
+ If you use the plugin within a single table inheritance (STI) design, the easiest way to specify a default
32
+ record is by implementing a class method on the subclass.
33
+
34
+ class Label < ActiveRecord::Base
35
+ acts_as_label
36
+ end
37
+
38
+ class BillingFrequency < Label
39
+ self.default
40
+ BillingFrequency.monthly
41
+ end
42
+ end
43
+
44
+
45
+
46
+ == License
47
+
48
+ Copyright (c) 2010 Coroutine LLC, released under the MIT license
@@ -0,0 +1,43 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'jeweler'
5
+
6
+
7
+ desc 'Default: run tests.'
8
+ task :default => [:test]
9
+
10
+
11
+ desc 'Test the plugin.'
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'lib'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+
19
+ desc 'Generate documentation for the plugin.'
20
+ Rake::RDocTask.new(:rdoc) do |rdoc|
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = 'acts_as_label'
23
+ rdoc.options << '--line-numbers --inline-source'
24
+ rdoc.rdoc_files.include('README')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
27
+
28
+
29
+ begin
30
+ Jeweler::Tasks.new do |gemspec|
31
+ gemspec.name = "acts_as_label"
32
+ gemspec.summary = "Gem version of acts_as_label Rails plugin."
33
+ gemspec.description = "This acts_as extension implements a system label and a friendly label on a class and centralizes the logic for performing validations and accessing items by system label."
34
+ gemspec.email = "jdugan@coroutine.com"
35
+ gemspec.homepage = "http://github.com/coroutine/acts_as_label"
36
+ gemspec.authors = ["John Dugan"]
37
+ gemspec.add_dependency "activesupport"
38
+ end
39
+ Jeweler::GemcutterTasks.new
40
+ rescue LoadError
41
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
42
+ end
43
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'acts_as_label'
2
+
3
+ ActiveRecord::Base.class_eval do
4
+ include Coroutine::Acts::Label
5
+ end
@@ -0,0 +1,164 @@
1
+ module Coroutine #:nodoc:
2
+ module Acts #:nodoc:
3
+ module Label #:nodoc:
4
+
5
+ def self.included(base) #:nodoc:
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+
10
+ module ClassMethods
11
+
12
+
13
+ # == Description
14
+ #
15
+ # This +acts_as+ extension implements a system label and a friendly label on a class and centralizes
16
+ # the logic for performing validations and accessing items by system label.
17
+ #
18
+ #
19
+ # == Usage
20
+ #
21
+ # Simple Example
22
+ #
23
+ # class BillingFrequency < ActiveRecord::Base
24
+ # has_many :subscriptions
25
+ # acts_as_label :default => :monthly
26
+ # end
27
+ #
28
+ # class Subscription < ActiveRecord::Base
29
+ # belongs_to :billing_frequency
30
+ # end
31
+ #
32
+ # subscription.billing_frequency = BillingFrequency.monthly
33
+ # subscription.billing_frequency = BillingFrequency.default
34
+ #
35
+ #
36
+ # STI Example:
37
+ #
38
+ # class Label < ActiveRecord::Base
39
+ # acts_as_label :scoped_to => :type
40
+ # end
41
+ #
42
+ # class BillingFrequency < Label
43
+ # has_many :subscriptions
44
+ # def self.default
45
+ # BillingFrequency.monthly
46
+ # end
47
+ # end
48
+ #
49
+ # class Subscription < ActiveRecord::Base
50
+ # belongs_to :billing_frequency
51
+ # end
52
+ #
53
+ # subscription.billing_frequency = BillingFrequency.monthly
54
+ # subscription.billing_frequency = BillingFrequency.default
55
+ #
56
+ #
57
+ # == Configuration
58
+ #
59
+ # * +system_label_cloumn+ - specifies the column name to use for storing the system label (default: +system_label+)
60
+ # * +label_column+ - specifies the column name to use for storing the label (default: +label+)
61
+ # * +default+ - specifies the system label value of the default instance (default: the first record in the default scope)
62
+ #
63
+ def acts_as_label(options = {})
64
+
65
+ #-------------------------------------------
66
+ # scrub options
67
+ #-------------------------------------------
68
+ options = {} unless options.is_a?(Hash)
69
+ system_label = options.key?(:system_label_column) ? options[:system_label_column].to_sym : :system_label
70
+ label = options.key?(:label_column) ? options[:label_column].to_sym : :label
71
+ scope = options.key?(:scope) ? options[:scope] : "1 = 1"
72
+ default = options.key?(:default) ? options[:default].to_sym : nil
73
+
74
+
75
+ #--------------------------------------------
76
+ # mix methods into class definition
77
+ #--------------------------------------------
78
+ class_eval do
79
+
80
+ # Add inheritable accessors
81
+ write_inheritable_attribute :acts_as_label_system_label_column, system_label
82
+ class_inheritable_reader :acts_as_label_system_label_column
83
+ write_inheritable_attribute :acts_as_label_label_column, label
84
+ class_inheritable_reader :acts_as_label_label_column
85
+ write_inheritable_attribute :acts_as_label_scope, scope
86
+ class_inheritable_reader :acts_as_label_scope
87
+ write_inheritable_attribute :acts_as_label_default_system_label, default
88
+ class_inheritable_reader :acts_as_label_default_system_label
89
+
90
+
91
+ # Add validations
92
+ validates_presence_of system_label
93
+ validates_length_of system_label, :maximum => 255
94
+ validates_format_of system_label, :with => /^[A-Z][_A-Z0-9]*$/
95
+ validates_presence_of label
96
+ validates_length_of label, :maximum => 255
97
+
98
+
99
+ # Add method missing, if needed
100
+ unless self.method_defined? :method_missing
101
+ def self.method_missing(method, *args, &block)
102
+ super
103
+ end
104
+ end
105
+
106
+ # Add custom method missing functionality to perform find by system label lookup. If
107
+ # nothing is found, it delegates the call to the original method_missing.
108
+ def self.method_missing_with_label(method, *args, &block)
109
+ record = self.find(:first, :conditions => ["#{acts_as_label_system_label_column} = ?", method.to_s.upcase])
110
+ if record
111
+ return record
112
+ else
113
+ method_missing_without_label(method, *args, &block)
114
+ end
115
+ end
116
+
117
+ # Add method missing alias
118
+ class << self
119
+ alias_method_chain :method_missing, :label
120
+ end
121
+
122
+ # Add class method to return default record, if needed
123
+ unless self.method_defined? :default
124
+ if default.nil?
125
+ def self.default
126
+ self.first
127
+ end
128
+ else
129
+ def self.default
130
+ self.send("#{acts_as_label_default_system_label}")
131
+ end
132
+ end
133
+ end
134
+
135
+
136
+ # Add all the instance methods
137
+ include Coroutine::Acts::Label::InstanceMethods
138
+
139
+ end
140
+ end
141
+ end
142
+
143
+
144
+ module InstanceMethods
145
+
146
+ # This method updates the system label attribute writer to ensure it is uppercase.
147
+ #
148
+ def system_label=(value)
149
+ value = value.to_s.strip.upcase unless value.nil?
150
+ write_attribute("#{acts_as_label_system_label_column}", value)
151
+ end
152
+
153
+
154
+ # This method overrides the to_s method to return the friendly label value.
155
+ #
156
+ def to_s
157
+ self.send("#{acts_as_label_label_column}")
158
+ end
159
+
160
+ end
161
+
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,259 @@
1
+ #---------------------------------------------------------
2
+ # Requirements
3
+ #---------------------------------------------------------
4
+
5
+ # all generic requirements are in the helper
6
+ require "test/test_helper"
7
+
8
+
9
+
10
+ #---------------------------------------------------------
11
+ # Database config
12
+ #---------------------------------------------------------
13
+
14
+ # establish db connection
15
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
16
+
17
+
18
+ # define and seed tables
19
+ def setup_db
20
+ ActiveRecord::Schema.define(:version => 1) do
21
+ create_table :labels do |t|
22
+ t.string :type, :limit => 255
23
+ t.string :system_label, :limit => 255
24
+ t.string :label, :limit => 255
25
+
26
+ t.timestamps
27
+ end
28
+
29
+ create_table :frameworks do |t|
30
+ t.string :system_name, :limit => 255
31
+ t.string :name, :limit => 255
32
+
33
+ t.timestamps
34
+ end
35
+ end
36
+
37
+ Role.create!({ :system_label => "SUPERUSER", :label => "Admin" })
38
+ Role.create!({ :system_label => "EMPLOYEE", :label => "Employee" })
39
+ Role.create!({ :system_label => "GUEST", :label => "Guest" })
40
+
41
+ BillingFrequency.create!({ :system_label => "MONTHLY", :label => "Monthly" })
42
+ BillingFrequency.create!({ :system_label => "QUARTERLY", :label => "Quarterly" })
43
+ BillingFrequency.create!({ :system_label => "YEARLY", :label => "Yearly" })
44
+
45
+ TaxFrequency.create!({ :system_label => "MONTHLY", :label => "Monthly" })
46
+ TaxFrequency.create!({ :system_label => "QUARTERLY", :label => "Quarterly" })
47
+ TaxFrequency.create!({ :system_label => "YEARLY", :label => "Yearly" })
48
+
49
+ Framework.create!({ :system_name => "RUBY_ON_RAILS", :name => "Rails" })
50
+ Framework.create!({ :system_name => "DJANGO", :name => "Django" })
51
+ end
52
+
53
+
54
+ # drop all tables
55
+ def teardown_db
56
+ ActiveRecord::Base.connection.tables.each do |table|
57
+ ActiveRecord::Base.connection.drop_table(table)
58
+ end
59
+ end
60
+
61
+
62
+
63
+ #---------------------------------------------------------
64
+ # Model definitions
65
+ #---------------------------------------------------------
66
+
67
+ # Labels (STI base)
68
+ class Label < ActiveRecord::Base
69
+ acts_as_label
70
+ end
71
+
72
+
73
+ # Roles (STI extension with default)
74
+ class Role < Label
75
+ def self.default
76
+ Role.guest
77
+ end
78
+ end
79
+
80
+
81
+ # BillingFrequency (STI extension without default)
82
+ class BillingFrequency < Label
83
+ validates_uniqueness_of :system_label, :scope => :type
84
+ end
85
+
86
+
87
+ # TaxFrequency (STI extension for testing duplicate system labels)
88
+ class TaxFrequency < Label
89
+ validates_uniqueness_of :system_label, :scope => :type
90
+ end
91
+
92
+
93
+ # Frameworks (stand-alone model with overrides)
94
+ class Framework < ActiveRecord::Base
95
+ acts_as_label :system_label_column => :system_name, :label_column => :name, :default => :ruby_on_rails
96
+ end
97
+
98
+
99
+
100
+ #---------------------------------------------------------
101
+ # Tests
102
+ #---------------------------------------------------------
103
+
104
+ class ActsAsLabelTest < ActiveSupport::TestCase
105
+
106
+ #---------------------------------------------
107
+ # setup and teardown delegations
108
+ #---------------------------------------------
109
+
110
+ def setup
111
+ setup_db
112
+ end
113
+ def teardown
114
+ teardown_db
115
+ end
116
+
117
+
118
+
119
+ #---------------------------------------------
120
+ # test validations
121
+ #---------------------------------------------
122
+
123
+ def test_validations_with_standard_columns
124
+
125
+ # get valid record
126
+ record = Role.new({ :system_label => "CUSTOMER", :label => "Client" })
127
+ assert record.valid?
128
+
129
+ # system label cannot be null
130
+ record.system_label = nil
131
+ assert !record.valid?
132
+
133
+ # system label cannot be blank
134
+ record.system_label = ""
135
+ assert !record.valid?
136
+
137
+ # system label cannot be longer than 255 characters
138
+ record.system_label = ""
139
+ 256.times { record.system_label << "x" }
140
+ assert !record.valid?
141
+
142
+ # system label cannot have illegal characters
143
+ record.system_label = "SUPER-USER"
144
+ assert !record.valid?
145
+
146
+ # reset system label
147
+ record.system_label = "CUSTOMER"
148
+ assert record.valid?
149
+
150
+ # label cannot be null
151
+ record.label = nil
152
+ assert !record.valid?
153
+
154
+ # label cannot be blank
155
+ record.label = ""
156
+ assert !record.valid?
157
+
158
+ # label cannot be longer than 255 characters
159
+ record.label = ""
160
+ 256.times { record.label << "x" }
161
+ assert !record.valid?
162
+
163
+ end
164
+
165
+
166
+ def test_validations_with_custom_columns
167
+
168
+ # get valid record
169
+ record = Framework.new({ :system_name => "SPRING", :name => "Spring" })
170
+ assert record.valid?
171
+
172
+ # system name cannot be null
173
+ record.system_name = nil
174
+ assert !record.valid?
175
+
176
+ # system name cannot be blank
177
+ record.system_name = ""
178
+ assert !record.valid?
179
+
180
+ # system name cannot be longer than 255 characters
181
+ record.system_name = ""
182
+ 256.times { record.system_name << "x" }
183
+ assert !record.valid?
184
+
185
+ # system name cannot have illegal characters
186
+ record.system_name = "SPRING-JAVA"
187
+ assert !record.valid?
188
+
189
+ # reset system name
190
+ record.system_name = "SPRING"
191
+ assert record.valid?
192
+
193
+ # name cannot be null
194
+ record.name = nil
195
+ assert !record.valid?
196
+
197
+ # name cannot be blank
198
+ record.name = ""
199
+ assert !record.valid?
200
+
201
+ # name cannot be longer than 255 characters
202
+ record.name = ""
203
+ 256.times { record.name << "x" }
204
+ assert !record.valid?
205
+
206
+ end
207
+
208
+
209
+ #---------------------------------------------
210
+ # test method missing
211
+ #---------------------------------------------
212
+
213
+ def test_method_missing_accessors
214
+
215
+ # test lookup by system label
216
+ assert_equal Role.find(:first, :conditions => ["system_label = ?", "SUPERUSER"]), Role.superuser
217
+
218
+ # test default with implemented method
219
+ assert_equal Role.find(:first, :conditions => ["system_label = ?", "GUEST"]), Role.default
220
+
221
+ # test default with unspecified behavior
222
+ assert_equal BillingFrequency.first, BillingFrequency.default
223
+
224
+ # test default with specified system label
225
+ assert_equal Framework.find(:first, :conditions => ["system_name = ?", "RUBY_ON_RAILS"]), Framework.default
226
+
227
+ end
228
+
229
+
230
+ def test_method_missing_finders
231
+
232
+ # dynamic find on stand-alone model
233
+ record = Framework.find_by_system_name("RUBY_ON_RAILS")
234
+ assert !record.nil?
235
+
236
+ #dynamic find on sti model
237
+ record = Role.find_by_system_label("SUPERUSER")
238
+ assert !record.nil?
239
+
240
+ end
241
+
242
+
243
+
244
+ #---------------------------------------------
245
+ # test instance methods
246
+ #---------------------------------------------
247
+
248
+ def test_to_s
249
+ role = Role.first
250
+ assert_equal role.label, role.to_s
251
+ end
252
+
253
+
254
+ def test_upcase_system_label_value
255
+ record = Role.create!({ :system_label => "Customer", :label => "Client" })
256
+ assert_equal record.system_label, "CUSTOMER"
257
+ end
258
+
259
+ end
@@ -0,0 +1,26 @@
1
+ # require rails stuff
2
+ require "rubygems"
3
+ require "active_record"
4
+ require "active_support"
5
+ require "active_support/test_case"
6
+ require "test/unit"
7
+
8
+ # require plugin
9
+ require "#{File.dirname(__FILE__)}/../init"
10
+
11
+
12
+
13
+ #----------------------------------------------------------
14
+ # Define global methods
15
+ #----------------------------------------------------------
16
+
17
+ class ActiveSupport::TestCase
18
+
19
+ # This method allows us to use a convenient notation for testing
20
+ # model validations.
21
+ def assert_not_valid(object, msg="Object is valid when it should be invalid")
22
+ assert(!object.valid?, msg)
23
+ end
24
+ alias :assert_invalid :assert_not_valid
25
+
26
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_label
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - John Dugan
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-10 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ description: This acts_as extension implements a system label and a friendly label on a class and centralizes the logic for performing validations and accessing items by system label.
33
+ email: jdugan@coroutine.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files:
39
+ - README.rdoc
40
+ files:
41
+ - .gitignore
42
+ - MIT-LICENSE
43
+ - README.rdoc
44
+ - Rakefile
45
+ - VERSION
46
+ - init.rb
47
+ - lib/acts_as_label.rb
48
+ - test/acts_as_label_test.rb
49
+ - test/test_helper.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/coroutine/acts_as_label
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options:
56
+ - --charset=UTF-8
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Gem version of acts_as_label Rails plugin.
80
+ test_files:
81
+ - test/acts_as_label_test.rb
82
+ - test/test_helper.rb