pluginaweek-smart_field_constraints 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ == master
2
+
3
+ == 0.1.1 / 2009-03-15
4
+
5
+ * Fix limits for integer columns being interpreted incorrectly [Michael Grosser]
6
+
7
+ == 0.1.0 / 2008-12-14
8
+
9
+ * Remove the PluginAWeek namespace
10
+ * Update tests to use ActionView::TestCase
11
+
12
+ == 0.0.2 / 2008-06-22
13
+
14
+ * Remove log files from gems
15
+ * Don't check length validation constraints if models were loaded prior to the plugin being loaded [Michael Grosser]
16
+ * Refactor FormHelper extension to allow for others to easily extend the plugin for things like textarea lengths [Michael Grosser]
17
+ * Add support for tracking validates_size_of validations
18
+
19
+ == 0.0.1 / 2008-05-05
20
+
21
+ * Initial public release
22
+ * Add documentation
23
+ * Remove maxlength attribute for textare tags since it's not valid html
24
+ * Don't set the size based on the smart maxlength
25
+ * Don't expect columns to exist for every attribute
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-2009 Aaron Pfeifer
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,92 @@
1
+ = smart_field_constraints
2
+
3
+ +smart_field_constraints+ intelligently applies a maxlength attribute for text
4
+ fields based on column constraints and validations.
5
+
6
+ == Resources
7
+
8
+ API
9
+
10
+ * http://api.pluginaweek.org/smart_field_constraints
11
+
12
+ Bugs
13
+
14
+ * http://pluginaweek.lighthouseapp.com/projects/13287-smart_field_constraints
15
+
16
+ Development
17
+
18
+ * http://github.com/pluginaweek/smart_field_constraints
19
+
20
+ Source
21
+
22
+ * git://github.com/pluginaweek/smart_field_constraints.git
23
+
24
+ == Description
25
+
26
+ HTML input field restrictions within forms can often help with both validation
27
+ and improving the user experience. Normally, adding the +maxlength+ configuration
28
+ option for input fields is not DRY and duplicates data already available in the
29
+ model or database. This plugin helps make this automatic.
30
+
31
+ +smart_field_constraints+ looks in two places for determining the maxlength value
32
+ for an input field:
33
+ * Model validates_length_of/validates_size_of validations
34
+ * Database column definitions (limits specifically)
35
+
36
+ Model validations will always take preference over database column definitions.
37
+
38
+ == Usage
39
+
40
+ There's nothing that you need to change to be able to use this plugin. It'll
41
+ just start automatically adding the +maxlength+ values it finds based on the
42
+ information described above (unless you define that option yourself).
43
+
44
+ === Example
45
+
46
+ Model:
47
+ class User < ActiveRecord::Base
48
+ validates_length_of :login, :maximum => 12
49
+ end
50
+
51
+ View:
52
+ text_field(:user, :login)
53
+
54
+ HTML:
55
+ <input id="user_login" maxlength="12" name="user[login]" size="30" type="text" />
56
+
57
+ === Textarea maxlengths
58
+
59
+ Since the +maxlength+ attribute is not W3C-compliant for textareas, it is not
60
+ included in the types of fields that will be automatically assigned length
61
+ constraints. However, you can easily add this yourself by extending the plugin
62
+ yourself. For an example of this see smart_field_constraints_textarea[http://github.com/grosser/smart_field_constraints_textarea].
63
+
64
+ == Caveats
65
+
66
+ === Plugin load order
67
+
68
+ If you have plugins with models that are loaded *before* smart_field_constraints
69
+ is loaded, then any length validations defined in those models will *not* be
70
+ tracked and automatically used in form fields. To fix this, you can adjust your
71
+ application's plugin load order to ensure that smart_field_constraints is loaded
72
+ first:
73
+
74
+ config/environment.rb:
75
+ Rails::Initializer.run do |config|
76
+ ...
77
+ config.plugins = [:smart_field_constraints, :all]
78
+ ...
79
+ end
80
+
81
+ == Testing
82
+
83
+ Before you can run any tests, the following gem must be installed:
84
+ * plugin_test_helper[http://github.com/pluginaweek/plugin_test_helper]
85
+
86
+ To run against a specific version of Rails:
87
+
88
+ rake test RAILS_FRAMEWORK_ROOT=/path/to/rails
89
+
90
+ == Dependencies
91
+
92
+ * Rails 2.0 or later
@@ -0,0 +1,96 @@
1
+ require 'rake/testtask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/contrib/sshpublisher'
5
+
6
+ spec = Gem::Specification.new do |s|
7
+ s.name = 'smart_field_constraints'
8
+ s.version = '0.1.1'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.summary = 'Intelligently applies a maxlength attribute for text fields based on column constraints and validations'
11
+ s.description = s.summary
12
+
13
+ s.files = FileList['{lib,test}/**/*'] + %w(CHANGELOG.rdoc init.rb LICENSE Rakefile README.rdoc) - FileList['test/app_root/{log,log/*,script,script/*}']
14
+ s.require_path = 'lib'
15
+ s.has_rdoc = true
16
+ s.test_files = Dir['test/**/*_test.rb']
17
+
18
+ s.author = 'Aaron Pfeifer'
19
+ s.email = 'aaron@pluginaweek.org'
20
+ s.homepage = 'http://www.pluginaweek.org'
21
+ s.rubyforge_project = 'pluginaweek'
22
+ end
23
+
24
+ desc 'Default: run all tests.'
25
+ task :default => :test
26
+
27
+ desc "Test the #{spec.name} plugin."
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.libs << 'lib'
30
+ t.test_files = spec.test_files
31
+ t.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ namespace :test do
37
+ desc "Test the #{spec.name} plugin with Rcov."
38
+ Rcov::RcovTask.new(:rcov) do |t|
39
+ t.libs << 'lib'
40
+ t.test_files = spec.test_files
41
+ t.rcov_opts << '--exclude="^(?!lib/)"'
42
+ t.verbose = true
43
+ end
44
+ end
45
+ rescue LoadError
46
+ end
47
+
48
+ desc "Generate documentation for the #{spec.name} plugin."
49
+ Rake::RDocTask.new(:rdoc) do |rdoc|
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = spec.name
52
+ rdoc.template = '../rdoc_template.rb'
53
+ rdoc.options << '--line-numbers' << '--inline-source'
54
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc', 'LICENSE', 'lib/**/*.rb')
55
+ end
56
+
57
+ desc 'Generate a gemspec file.'
58
+ task :gemspec do
59
+ File.open("#{spec.name}.gemspec", 'w') do |f|
60
+ f.write spec.to_ruby
61
+ end
62
+ end
63
+
64
+ Rake::GemPackageTask.new(spec) do |p|
65
+ p.gem_spec = spec
66
+ p.need_tar = true
67
+ p.need_zip = true
68
+ end
69
+
70
+ desc 'Publish the beta gem.'
71
+ task :pgem => [:package] do
72
+ Rake::SshFilePublisher.new('aaron@pluginaweek.org', '/home/aaron/gems.pluginaweek.org/public/gems', 'pkg', "#{spec.name}-#{spec.version}.gem").upload
73
+ end
74
+
75
+ desc 'Publish the API documentation.'
76
+ task :pdoc => [:rdoc] do
77
+ Rake::SshDirPublisher.new('aaron@pluginaweek.org', "/home/aaron/api.pluginaweek.org/public/#{spec.name}", 'rdoc').upload
78
+ end
79
+
80
+ desc 'Publish the API docs and gem'
81
+ task :publish => [:pgem, :pdoc, :release]
82
+
83
+ desc 'Publish the release files to RubyForge.'
84
+ task :release => [:gem, :package] do
85
+ require 'rubyforge'
86
+
87
+ ruby_forge = RubyForge.new.configure
88
+ ruby_forge.login
89
+
90
+ %w(gem tgz zip).each do |ext|
91
+ file = "pkg/#{spec.name}-#{spec.version}.#{ext}"
92
+ puts "Releasing #{File.basename(file)}..."
93
+
94
+ ruby_forge.add_release(spec.rubyforge_project, spec.name, spec.version, file)
95
+ end
96
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'smart_field_constraints'
@@ -0,0 +1,2 @@
1
+ require 'smart_field_constraints/extensions/form_helper'
2
+ require 'smart_field_constraints/extensions/validations'
@@ -0,0 +1,62 @@
1
+ module SmartFieldConstraints
2
+ module Extensions #:nodoc:
3
+ # Automatically applies the maximum length for an input field if it can be
4
+ # determined
5
+ module InstanceTag
6
+ def self.included(base) #:nodoc:
7
+ base.class_eval do
8
+ alias_method_chain :to_input_field_tag, :smart_constraints
9
+ end
10
+ end
11
+
12
+ # Apply constraints for the given field
13
+ def to_input_field_tag_with_smart_constraints(field_type, options = {})
14
+ # Only check password and text fields
15
+ add_max_length_constraints(options) if %w(password text).include?(field_type)
16
+
17
+ to_input_field_tag_without_smart_constraints(field_type, options)
18
+ end
19
+
20
+ private
21
+ def add_max_length_constraints(options)
22
+ options.stringify_keys!
23
+ return if options['maxlength'] || !object
24
+
25
+ # Look for the attribute's maximum length from tracked validations or
26
+ # the column's definition
27
+ if max_length = validation_length || column_limit
28
+ # If the size isn't specified, use the caller's maxlength of the default value.
29
+ # This must be done here, otherwise it'll use the maxlength value that
30
+ # we apply here
31
+ options['size'] ||= options['maxlength'] || ActionView::Helpers::InstanceTag::DEFAULT_FIELD_OPTIONS['size']
32
+ options['maxlength'] = max_length
33
+ end
34
+ end
35
+
36
+ # Finds the maximum length according to validations
37
+ def validation_length
38
+ if constraints = object.class.smart_length_constraints
39
+ constraints[method_name]
40
+ end
41
+ end
42
+
43
+ # Finds the maximum length according to column limits
44
+ def column_limit
45
+ column = object.class.columns_hash[method_name]
46
+
47
+ if column && limit = column.limit
48
+ if column.text?
49
+ limit
50
+ elsif column.number?
51
+ # Length is bound by the upper limit of the number + 1 (for negatives)
52
+ Math.log10(2 ** (limit * 8 - 1)).ceil + 1
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ ActionView::Helpers::InstanceTag.class_eval do
61
+ include SmartFieldConstraints::Extensions::InstanceTag
62
+ end
@@ -0,0 +1,74 @@
1
+ module SmartFieldConstraints
2
+ module Extensions #:nodoc:
3
+ # Tracks validations on the length of fields so that they can be used when
4
+ # generating form tags for those fields
5
+ module Validations
6
+ def self.included(base) #:nodoc:
7
+ base.class_eval do
8
+ extend SmartFieldConstraints::Extensions::Validations::ClassMethods
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ def self.extended(base) #:nodoc:
14
+ base.class_eval do
15
+ class_inheritable_hash :smart_length_constraints
16
+ self.smart_length_constraints = {}
17
+ end
18
+
19
+ class << base
20
+ alias_method_chain :validates_length_of, :smart_constraints
21
+ alias_method_chain :validates_size_of, :smart_constraints
22
+ end
23
+ end
24
+
25
+ # Tracks what the maximum value is that's allowed for all of the
26
+ # attributes being validated
27
+ def validates_length_of_with_smart_constraints(*attrs)
28
+ track_length_constraints(attrs)
29
+ validates_length_of_without_smart_constraints(*attrs)
30
+ end
31
+
32
+ # Tracks what the maximum value is that's allowed for all of the
33
+ # attributes being validated
34
+ def validates_size_of_with_smart_constraints(*attrs)
35
+ track_length_constraints(attrs)
36
+ validates_size_of_without_smart_constraints(*attrs)
37
+ end
38
+
39
+ private
40
+ def track_length_constraints(attrs)
41
+ options = attrs.last
42
+ if options.is_a?(Hash)
43
+ # Extract the option restricting the length
44
+ options = options.symbolize_keys
45
+ range_options = ActiveRecord::Validations::ClassMethods::ALL_RANGE_OPTIONS & options.keys
46
+ option = range_options.first
47
+ option_value = options[range_options.first]
48
+
49
+ # Find the max value from ranges or specific maximums
50
+ max_length = nil
51
+ case option
52
+ when :within, :in
53
+ max_length = option_value.end
54
+ when :maximum, :is
55
+ max_length = option_value
56
+ end
57
+
58
+ if max_length
59
+ # Store the maximum value for each attribute so that it can be referenced later
60
+ attrs.each do |attr|
61
+ self.smart_length_constraints ||= {}
62
+ self.smart_length_constraints[attr.to_s] = max_length
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ ActiveRecord::Base.class_eval do
73
+ include SmartFieldConstraints::Extensions::Validations
74
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,8 @@
1
+ require 'config/boot'
2
+
3
+ Rails::Initializer.run do |config|
4
+ config.plugins = %w(tags smart_field_constraints)
5
+ config.cache_classes = false
6
+ config.whiny_nils = true
7
+ config.action_controller.session = {:key => 'rails_session', :secret => 'd229e4d22437432705ab3985d4d246'}
8
+ end
@@ -0,0 +1,14 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users, :id => false do |t|
4
+ t.integer :id, :limit => 4, :null => false # For limit for testing purposes
5
+ t.string :login, :limit => 12
6
+ t.string :password, :limit => 16
7
+ t.text :biography
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :users
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class CreateTags < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :tags do |t|
4
+ t.string :name, :limit => 100
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_table :tags
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ require 'tag'
@@ -0,0 +1,3 @@
1
+ class Tag < ActiveRecord::Base
2
+ validates_length_of :name, :maximum => 30
3
+ end
@@ -0,0 +1,110 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class FormHelperWithoutConstraintsTest < ActionView::TestCase
4
+ tests ActionView::Helpers::FormHelper
5
+
6
+ def setup
7
+ @user = User.new
8
+ end
9
+
10
+ def test_should_not_add_maxlength_for_text_field
11
+ assert_equal '<input id="user_biography" name="user[biography]" size="30" type="text" />', text_field(:user, :biography)
12
+ end
13
+
14
+ def test_should_not_add_maxlength_for_password_field
15
+ assert_equal '<input id="user_biography" name="user[biography]" size="30" type="password" />', password_field(:user, :biography)
16
+ end
17
+ end
18
+
19
+ class FormHelperWithValidationConstraintsTest < ActionView::TestCase
20
+ tests ActionView::Helpers::FormHelper
21
+
22
+ def setup
23
+ User.validates_length_of :biography, :maximum => 120
24
+ User.validates_length_of :password, :maximum => 14
25
+
26
+ @user = User.new
27
+ end
28
+
29
+ def test_should_not_add_maxlength_for_text_area
30
+ assert_equal '<textarea cols="40" id="user_biography" name="user[biography]" rows="20"></textarea>', text_area(:user, :biography)
31
+ end
32
+
33
+ def test_should_not_add_maxlength_for_hidden_field
34
+ assert_equal '<input id="user_password" name="user[password]" type="hidden" />', hidden_field(:user, :password)
35
+ end
36
+
37
+ def test_should_add_maxlength_for_password_field
38
+ assert_equal '<input id="user_password" maxlength="14" name="user[password]" size="30" type="password" />', password_field(:user, :password)
39
+ end
40
+
41
+ def test_should_add_maxlength_for_text_field
42
+ assert_equal '<input id="user_biography" maxlength="120" name="user[biography]" size="30" type="text" />', text_field(:user, :biography)
43
+ end
44
+
45
+ def test_should_allow_maxlength_to_be_overridden
46
+ assert_equal '<input id="user_biography" maxlength="100" name="user[biography]" size="100" type="text" />', text_field(:user, :biography, :maxlength => 100)
47
+ end
48
+
49
+ def teardown
50
+ User.class_eval do
51
+ ActiveRecord::Validations::VALIDATIONS.each do |validation|
52
+ instance_variable_set("@#{validation}_callbacks", nil)
53
+ end
54
+ end
55
+
56
+ User.smart_length_constraints.clear
57
+ end
58
+ end
59
+
60
+ class FormHelperWithStringColumnConstraintsTest < ActionView::TestCase
61
+ tests ActionView::Helpers::FormHelper
62
+
63
+ def setup
64
+ @user = User.new
65
+ end
66
+
67
+ def test_should_not_add_maxlength_for_text_area
68
+ assert_equal '<textarea cols="40" id="user_login" name="user[login]" rows="20"></textarea>', text_area(:user, :login)
69
+ end
70
+
71
+ def test_should_not_add_maxlength_for_hidden_field
72
+ assert_equal '<input id="user_password" name="user[password]" type="hidden" />', hidden_field(:user, :password)
73
+ end
74
+
75
+ def test_should_add_maxlength_for_password_field
76
+ assert_equal '<input id="user_password" maxlength="16" name="user[password]" size="30" type="password" />', password_field(:user, :password)
77
+ end
78
+
79
+ def test_should_add_maxlength_for_text_field
80
+ assert_equal '<input id="user_login" maxlength="12" name="user[login]" size="30" type="text" />', text_field(:user, :login)
81
+ end
82
+
83
+ def test_should_allow_maxlength_to_be_overridden
84
+ assert_equal '<input id="user_login" maxlength="100" name="user[login]" size="100" type="text" />', text_field(:user, :login, :maxlength => 100)
85
+ end
86
+ end
87
+
88
+ class FormHelperWithNumberColumnConstraintsTest < ActionView::TestCase
89
+ tests ActionView::Helpers::FormHelper
90
+
91
+ def setup
92
+ @user = User.new
93
+ end
94
+
95
+ def test_should_add_maxlength
96
+ assert_equal '<input id="user_id" maxlength="11" name="user[id]" size="30" type="text" />', text_field(:user, :id)
97
+ end
98
+ end
99
+
100
+ class FormHelperForModelNotTrackedTest < ActionView::TestCase
101
+ tests ActionView::Helpers::FormHelper
102
+
103
+ def setup
104
+ @tag = Tag.new
105
+ end
106
+
107
+ def test_should_add_maxlength_based_on_column_constraints
108
+ assert_equal '<input id="tag_name" maxlength="100" name="tag[name]" size="30" type="text" />', text_field(:tag, :name)
109
+ end
110
+ end
@@ -0,0 +1,7 @@
1
+ # Load the plugin testing framework
2
+ $:.unshift("#{File.dirname(__FILE__)}/../../plugin_test_helper/lib")
3
+ require 'rubygems'
4
+ require 'plugin_test_helper'
5
+
6
+ # Run the migrations
7
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class ModelWithoutLengthValidationsTest < ActiveSupport::TestCase
4
+ def test_should_not_have_any_constraints
5
+ assert User.smart_length_constraints.empty?
6
+ end
7
+ end
8
+
9
+ class ModelWithLengthValidationsTest < ActiveSupport::TestCase
10
+ def test_should_not_track_constraint_for_minimum
11
+ User.validates_length_of :name, :minimum => 1
12
+ assert_nil User.smart_length_constraints['name']
13
+ end
14
+
15
+ def test_should_track_constraint_for_within
16
+ User.validates_length_of :name, :within => 1..10
17
+ assert_equal 10, User.smart_length_constraints['name']
18
+ end
19
+
20
+ def test_should_track_constraint_for_in
21
+ User.validates_length_of :name, :in => 1..10
22
+ assert_equal 10, User.smart_length_constraints['name']
23
+ end
24
+
25
+ def test_should_track_constraint_for_maximum
26
+ User.validates_length_of :name, :maximum => 10
27
+ assert_equal 10, User.smart_length_constraints['name']
28
+ end
29
+
30
+ def test_should_track_validation_for_is
31
+ User.validates_length_of :name, :is => 10
32
+ assert_equal 10, User.smart_length_constraints['name']
33
+ end
34
+
35
+ def teardown
36
+ User.class_eval do
37
+ ActiveRecord::Validations::VALIDATIONS.each do |validation|
38
+ instance_variable_set("@#{validation}_callbacks", nil)
39
+ end
40
+ end
41
+
42
+ User.smart_length_constraints.clear
43
+ end
44
+ end
45
+
46
+ class ModelWithSizeValidationsTest < ActiveSupport::TestCase
47
+ def test_should_track_constraints
48
+ User.validates_size_of :name, :maximum => 10
49
+ assert_equal 10, User.smart_length_constraints['name']
50
+ end
51
+
52
+ def teardown
53
+ User.class_eval do
54
+ ActiveRecord::Validations::VALIDATIONS.each do |validation|
55
+ instance_variable_set("@#{validation}_callbacks", nil)
56
+ end
57
+ end
58
+
59
+ User.smart_length_constraints.clear
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pluginaweek-smart_field_constraints
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Pfeifer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Intelligently applies a maxlength attribute for text fields based on column constraints and validations
17
+ email: aaron@pluginaweek.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/smart_field_constraints
26
+ - lib/smart_field_constraints/extensions
27
+ - lib/smart_field_constraints/extensions/validations.rb
28
+ - lib/smart_field_constraints/extensions/form_helper.rb
29
+ - lib/smart_field_constraints.rb
30
+ - test/unit
31
+ - test/unit/validations_test.rb
32
+ - test/helpers
33
+ - test/helpers/form_helper_test.rb
34
+ - test/app_root
35
+ - test/app_root/app
36
+ - test/app_root/app/models
37
+ - test/app_root/app/models/user.rb
38
+ - test/app_root/vendor
39
+ - test/app_root/vendor/plugins
40
+ - test/app_root/vendor/plugins/tags
41
+ - test/app_root/vendor/plugins/tags/lib
42
+ - test/app_root/vendor/plugins/tags/lib/tag.rb
43
+ - test/app_root/vendor/plugins/tags/init.rb
44
+ - test/app_root/db
45
+ - test/app_root/db/migrate
46
+ - test/app_root/db/migrate/001_create_users.rb
47
+ - test/app_root/db/migrate/002_create_tags.rb
48
+ - test/app_root/config
49
+ - test/app_root/config/environment.rb
50
+ - test/test_helper.rb
51
+ - CHANGELOG.rdoc
52
+ - init.rb
53
+ - LICENSE
54
+ - Rakefile
55
+ - README.rdoc
56
+ has_rdoc: true
57
+ homepage: http://www.pluginaweek.org
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project: pluginaweek
78
+ rubygems_version: 1.2.0
79
+ signing_key:
80
+ specification_version: 2
81
+ summary: Intelligently applies a maxlength attribute for text fields based on column constraints and validations
82
+ test_files:
83
+ - test/unit/validations_test.rb
84
+ - test/helpers/form_helper_test.rb