valle 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ ## 0.0.2 / 2012-12-11
2
+
3
+ * fixed inherited behavior; switched to valid? method (Fixes #3) [Anton Kalyaev]
4
+ * added support for integer columns [Anton Kalyaev]
5
+ * added 3 types of columns: character_limited, byte_limited and unlimited [Anton Kalyaev]
6
+ * removed engine [Anton Kalyaev]
7
+ * fix typos in README.md [Aleksandr Ivanov]
8
+
9
+ ## 0.0.1 / 2012-12-09
10
+
11
+ * Initial release (with basic strings support)
data/README.md CHANGED
@@ -9,14 +9,14 @@ hands.
9
9
 
10
10
  validates :field_name, length: { maximum: 255 }
11
11
 
12
- Note: If you do not do this (and usually you are) and try to enter 2147483648 into the field with type: `interger` (see [Numeric types](http://www.postgresql.org/docs/9.2/static/datatype-numeric.html) section of PostgreSQL docs), you will get 500 error.
12
+ Note: If you do not do this (and usually you are) and try to enter 2147483648 into the field with type: `integer` (see [Numeric types](http://www.postgresql.org/docs/9.2/static/datatype-numeric.html) section of PostgreSQL docs), you will get 500 error.
13
13
 
14
14
  Example:
15
15
 
16
16
  PG::Error: ERROR: value "2147483648" is out of range for type integer
17
17
  : SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1
18
18
 
19
- There is a simular gem, called [validates_lengths_from_database](http://github.com/rubiety/validates_lengths_from_database). It solves only one part -
19
+ There is a similar gem, called [validates_lengths_from_database](http://github.com/rubiety/validates_lengths_from_database). It solves only one part -
20
20
  applicable to strings. This gem is designed to work with all possible field types.
21
21
 
22
22
  ## Installation
@@ -59,12 +59,16 @@ Also, you should be able to turn it off temporary by setting `enabled` option to
59
59
  5. Push to the branch (`git push origin my-new-feature`)
60
60
  6. Create new Pull Request
61
61
 
62
- ## Core team
62
+ ## Credits
63
+
64
+ Team members:
63
65
 
64
66
  - [Anton Kalyaev](http://github.com/akalyaev)
65
67
  - [Andrew Kulakov](http://github.com/Andrew8xx8)
66
68
  - [Alexander Kirillov](http://github.com/saratovsource)
67
69
 
70
+ Thank you to all our amazing [contributors](http://github.com/kaize/valle/contributors)!
71
+
68
72
  ## License
69
73
 
70
74
  Valle is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'cucumber/rake/task'
5
5
 
6
6
  Rake::TestTask.new do |t|
7
7
  t.libs << "test"
8
- t.test_files = FileList['test/lib/*_test.rb']
8
+ t.test_files = FileList['test/lib/**/*_test.rb']
9
9
  t.verbose = true
10
10
  end
11
11
 
@@ -11,6 +11,8 @@ Feature: adds validators
11
11
  def self.up
12
12
  create_table :users do |t|
13
13
  t.string :name
14
+ t.text :bio
15
+ t.integer :age
14
16
  end
15
17
  end
16
18
  end
@@ -23,12 +25,14 @@ Feature: adds validators
23
25
  """
24
26
 
25
27
  @disable-bundler
26
- Scenario: generate a rails 3 application and use factory definitions
28
+ Scenario: generate a rails 3 application and try out automatically injected validations
27
29
  When I write to "test/factories.rb" with:
28
30
  """
29
31
  FactoryGirl.define do
30
32
  factory :user do
31
33
  name "John"
34
+ bio "A nice write up about this guy"
35
+ age 22
32
36
  end
33
37
  end
34
38
  """
@@ -4,24 +4,21 @@ module Valle
4
4
  extend Configuration
5
5
 
6
6
  # core
7
- autoload :BoundMapper, 'valle/bound_mapper'
8
7
  autoload :BoundsManager, 'valle/bounds_manager'
9
8
  autoload :ValidationSetter, 'valle/validation_setter'
10
9
 
10
+ # extensions
11
+ module AbstractAdapter
12
+ autoload :ColumnWrapper, 'valle/abstract_adapter/column_wrapper'
13
+ autoload :AbstractColumn, 'valle/abstract_adapter/abstract_column'
14
+ autoload :ByteLimitedColumn, 'valle/abstract_adapter/byte_limited_column'
15
+ autoload :CharacterLimitedColumn, 'valle/abstract_adapter/character_limited_column'
16
+ autoload :UnlimitedColumn, 'valle/abstract_adapter/unlimited_column'
17
+ end
18
+
11
19
  # hooks
12
20
  autoload :Hooks, 'valle/hooks'
13
21
  end
14
22
 
15
- # load Rails/Railtie
16
- begin
17
- require 'rails'
18
- rescue LoadError
19
- #do nothing
20
- end
21
-
22
- # if not using Railtie, call `Valle::Hooks.init` directly
23
- # TODO [AK 09/12/12] move this block to initializers
24
- if defined? Rails
25
- require 'valle/railtie'
26
- require 'valle/engine'
27
- end
23
+ ## if not using Railtie, call `Valle::Hooks.init` directly
24
+ require 'valle/railtie' if defined? Rails
@@ -0,0 +1,48 @@
1
+ module Valle
2
+ module AbstractAdapter
3
+ class AbstractColumn
4
+
5
+ ##
6
+ # Adds more functionality to the standard ActiveRecord::ConnectionAdapters::Column
7
+ #
8
+ # @param [ActiveRecord::ConnectionAdapters::Column] original_column the original column
9
+ #
10
+ # @example
11
+ # c = AbstractAdapter::AbstractColumn.new(original_column)
12
+ #
13
+ # c.minimum
14
+ # => -128
15
+ # c.maximum
16
+ # => 127
17
+ #
18
+ def initialize(original_column)
19
+ @original_column = original_column
20
+ end
21
+
22
+ ##
23
+ # Proxy all methods missing to original column
24
+ #
25
+ def method_missing(method_name, *arguments, &block)
26
+ @original_column.send(method_name, *arguments, &block)
27
+ end
28
+
29
+ def respond_to_method_missing?(method_name, include_private = false)
30
+ @original_column.respond_to?(method_name)
31
+ end
32
+
33
+ ##
34
+ # Get maximum possible value/length for this column
35
+ #
36
+ def maximum
37
+ raise NotImplementedError.new("You must implement maximum method.")
38
+ end
39
+
40
+ ##
41
+ # Get minimum value/length for this column
42
+ #
43
+ def minimum
44
+ raise NotImplementedError.new("You must implement minimum method.")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ module Valle
2
+ module AbstractAdapter
3
+ class ByteLimitedColumn < AbstractColumn
4
+
5
+ def maximum
6
+ case limit
7
+ when 1; 127
8
+ when 2; 32767
9
+ when 3; 8388607
10
+ when 4; 2147483647
11
+ when 8; 9223372036854775807
12
+ end
13
+ end
14
+
15
+ def minimum
16
+ case limit
17
+ when 1; -128
18
+ when 2; -32768
19
+ when 3; -8388608
20
+ when 4; -2147483648
21
+ when 8; -9223372036854775808
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ module Valle
2
+ module AbstractAdapter
3
+ class CharacterLimitedColumn < AbstractColumn
4
+
5
+ def maximum
6
+ limit
7
+ end
8
+
9
+ def minimum
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+ module Valle
2
+ module AbstractAdapter
3
+ class ColumnWrapper
4
+
5
+ class << self
6
+
7
+ ##
8
+ # Wraps original column
9
+ #
10
+ # @param [ActiveRecord::ConnectionAdapters::Column] original_column the original column
11
+ #
12
+ def wrap(original_column)
13
+ case
14
+ when limit_in_bytes?(original_column)
15
+ ByteLimitedColumn.new(original_column)
16
+ when limit_in_characters?(original_column)
17
+ CharacterLimitedColumn.new(original_column)
18
+ else
19
+ UnlimitedColumn.new(original_column)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ ##
26
+ # Determines whether the limit's method returned value is count of bytes
27
+ #
28
+ # Limit is number of bytes for :binary and :integer columns.
29
+ # @see http://apidock.com/rails/ActiveRecord/ConnectionAdapters/TableDefinition/column
30
+ #
31
+ def limit_in_bytes?(column)
32
+ case column.type
33
+ # when :binary; true
34
+ when :integer; true
35
+ else false
36
+ end
37
+ end
38
+
39
+ ##
40
+ # Determines whether the limit's method returned value is count of characters
41
+ #
42
+ # Limit is number of characters for :string and :text columns
43
+ # @see http://apidock.com/rails/ActiveRecord/ConnectionAdapters/TableDefinition/column
44
+ #
45
+ def limit_in_characters?(column)
46
+ case column.type
47
+ when :string; true
48
+ when :text; true
49
+ else false
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,12 @@
1
+ module Valle
2
+ module AbstractAdapter
3
+ class UnlimitedColumn < AbstractColumn
4
+
5
+ def maximum
6
+ end
7
+
8
+ def minimum
9
+ end
10
+ end
11
+ end
12
+ end
@@ -6,19 +6,13 @@ module Valle
6
6
  ##
7
7
  # Add validators for all columns of a given class
8
8
  #
9
- # 2 steps:
10
- # 1) get bound for the column
11
- # 2) set validation
12
- #
13
9
  # @param [ActiveRecord::Base] klass the AR model class
14
10
  #
15
11
  def add_validators(klass)
16
- mapper = BoundMapper.new
17
-
18
12
  columns = klass.columns
19
- columns.each do |column|
20
- bound = mapper.bound(column)
21
- ValidationSetter.add_validator(bound, column, klass)
13
+ columns.each do |original_column|
14
+ column = AbstractAdapter::ColumnWrapper.wrap(original_column)
15
+ ValidationSetter.add_validator(column, klass)
22
16
  end
23
17
  end
24
18
  end
@@ -3,17 +3,51 @@ module Valle
3
3
 
4
4
  class << self
5
5
 
6
+ ##
7
+ # Runs all the hooks, required for this gem
8
+ #
6
9
  def init
7
10
  ActiveSupport.on_load(:active_record) do
8
- ActiveRecord::Base.class_eval do
9
- # TODO [AK 09/12/12] possible we should run it after the class was inherited
10
- # @see http://stackoverflow.com/q/7093992/820520
11
- def self.inherited(subclass)
12
- Valle::BoundsManager.add_validators(subclass)
11
+ Valle::Hooks.extend_inherited_method
12
+ end
13
+ end
14
+
15
+ ##
16
+ # Extends the functionality of inherited method
17
+ #
18
+ def extend_inherited_method
19
+ ActiveRecord::Base.class_eval do
20
+ class << self
21
+ def inherited_with_valle_validators(subclass)
22
+ inherited_without_valle_validators(subclass)
23
+ Valle::Hooks.extend_ar_validations_valid_method(subclass)
13
24
  end
25
+
26
+ alias_method_chain :inherited, :valle_validators
14
27
  end
15
28
  end
16
29
  end
30
+
31
+ ##
32
+ # Extends the functionality of ActiveRecord::Validations valid? method
33
+ #
34
+ # @param [ActiveRecord::Base] subclass the AR::Base child class
35
+ # @note ActiveRecord::Validations should be defined at this point
36
+ #
37
+ def extend_ar_validations_valid_method(subclass)
38
+ subclass.instance_eval do
39
+ cattr_accessor :valle_validators
40
+ end
41
+
42
+ subclass.class_eval do
43
+ def valid_with_valle_validators?(context = nil)
44
+ self.class.valle_validators ||= Valle::BoundsManager.add_validators(self.class)
45
+ valid_without_valle_validators?(context)
46
+ end
47
+
48
+ alias_method_chain :valid?, :valle_validators
49
+ end
50
+ end
17
51
  end
18
52
  end
19
53
  end
@@ -5,14 +5,20 @@ module Valle
5
5
  ##
6
6
  # Adds validator to the klass column depending on its type
7
7
  #
8
- # @param [Bound] bound the bound
9
- # @param [Column] column the column
8
+ # @param [AbstractAdapter::AbstractColumn] column the column
10
9
  # @param [ActiveRecord::Base] klass the AR model class
11
10
  #
12
- def add_validator(bound, column, klass)
11
+ def add_validator(column, klass)
12
+ options = {}
13
+ options[:minimum] = column.minimum if column.minimum
14
+ options[:maximum] = column.maximum if column.maximum
15
+ return false unless options.present?
16
+
13
17
  case column.type
14
- when :string
15
- klass.validates column.name, length: { maximum: bound.maximum }
18
+ when :string, :text
19
+ klass.validates column.name, length: options
20
+ when :integer
21
+ klass.validates column.name, numericality: options
16
22
  end
17
23
  end
18
24
  end
@@ -1,3 +1,3 @@
1
1
  module Valle
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,25 @@
1
+ require "test_helper"
2
+
3
+ class CharacterLimitedColumnTest < TestCase
4
+
5
+ def test_maximum_should_return_value_for_string_column
6
+ original_column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "string(255)")
7
+ column = Valle::AbstractAdapter::CharacterLimitedColumn.new(original_column)
8
+
9
+ assert column.maximum
10
+ end
11
+
12
+ def test_maximum_should_return_correct_value_for_string_column_if_user_redefine_limit
13
+ original_column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "string(200)")
14
+ column = Valle::AbstractAdapter::CharacterLimitedColumn.new(original_column)
15
+
16
+ assert_equal 200, column.maximum
17
+ end
18
+
19
+ def test_minimum_should_return_nil
20
+ original_column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "string")
21
+ column = Valle::AbstractAdapter::CharacterLimitedColumn.new(original_column)
22
+
23
+ assert_nil column.minimum
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ require "test_helper"
2
+ require "active_record"
3
+
4
+ class ColumnWrapperTest < TestCase
5
+
6
+ def test_wrap_should_return_instance_of_character_limited_column_for_string_column
7
+ column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "string")
8
+ wrapped_column = Valle::AbstractAdapter::ColumnWrapper.wrap(column)
9
+
10
+ assert wrapped_column.is_a?(Valle::AbstractAdapter::CharacterLimitedColumn)
11
+ end
12
+
13
+ def test_wrap_should_return_instance_of_byte_limited_column_for_int_column
14
+ column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "int")
15
+ wrapped_column = Valle::AbstractAdapter::ColumnWrapper.wrap(column)
16
+
17
+ assert wrapped_column.is_a?(Valle::AbstractAdapter::ByteLimitedColumn)
18
+ end
19
+ end
@@ -1,6 +1,8 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.require
3
3
 
4
+ require "active_record"
5
+
4
6
  MiniTest::Unit.autorun
5
7
 
6
8
  class TestCase < MiniTest::Unit::TestCase
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-09 00:00:00.000000000 Z
12
+ date: 2012-12-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -53,6 +53,7 @@ extra_rdoc_files: []
53
53
  files:
54
54
  - .gitignore
55
55
  - .travis.yml
56
+ - CHANGELOG.md
56
57
  - Gemfile
57
58
  - Guardfile
58
59
  - LICENSE
@@ -62,15 +63,19 @@ files:
62
63
  - features/step_definitions/rails_steps.rb
63
64
  - features/support/env.rb
64
65
  - lib/valle.rb
65
- - lib/valle/bound_mapper.rb
66
+ - lib/valle/abstract_adapter/abstract_column.rb
67
+ - lib/valle/abstract_adapter/byte_limited_column.rb
68
+ - lib/valle/abstract_adapter/character_limited_column.rb
69
+ - lib/valle/abstract_adapter/column_wrapper.rb
70
+ - lib/valle/abstract_adapter/unlimited_column.rb
66
71
  - lib/valle/bounds_manager.rb
67
72
  - lib/valle/configuration.rb
68
- - lib/valle/engine.rb
69
73
  - lib/valle/hooks.rb
70
74
  - lib/valle/railtie.rb
71
75
  - lib/valle/validation_setter.rb
72
76
  - lib/valle/version.rb
73
- - test/lib/bound_mapper_test.rb
77
+ - test/lib/abstract_adapter/character_limited_column_test.rb
78
+ - test/lib/abstract_adapter/column_wrapper_test.rb
74
79
  - test/test_helper.rb
75
80
  - valle.gemspec
76
81
  homepage: http://github.com/kaize/valle
@@ -87,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
92
  version: '0'
88
93
  segments:
89
94
  - 0
90
- hash: -1528972839465003213
95
+ hash: 1761133230881238709
91
96
  required_rubygems_version: !ruby/object:Gem::Requirement
92
97
  none: false
93
98
  requirements:
@@ -96,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
101
  version: '0'
97
102
  segments:
98
103
  - 0
99
- hash: -1528972839465003213
104
+ hash: 1761133230881238709
100
105
  requirements: []
101
106
  rubyforge_project:
102
107
  rubygems_version: 1.8.24
@@ -108,5 +113,6 @@ test_files:
108
113
  - features/adds_validators.feature
109
114
  - features/step_definitions/rails_steps.rb
110
115
  - features/support/env.rb
111
- - test/lib/bound_mapper_test.rb
116
+ - test/lib/abstract_adapter/character_limited_column_test.rb
117
+ - test/lib/abstract_adapter/column_wrapper_test.rb
112
118
  - test/test_helper.rb
@@ -1,36 +0,0 @@
1
- module Valle
2
-
3
- Bound = Struct.new :minimum, :maximum
4
-
5
- class BoundMapper
6
-
7
- ##
8
- # Returns a new bound for the column
9
- #
10
- # @param [Column] column the column
11
- #
12
- def bound(column)
13
- Bound.new minimum(column), maximum(column)
14
- end
15
-
16
- private
17
-
18
- ##
19
- # Get the lower limit for a given column
20
- #
21
- # @param [Column] column the column
22
- #
23
- def minimum(column)
24
-
25
- end
26
-
27
- ##
28
- # Get the upper limit for a given column
29
- #
30
- # @param [Column] column the column
31
- #
32
- def maximum(column)
33
- column.limit
34
- end
35
- end
36
- end
@@ -1,4 +0,0 @@
1
- module Valle#:nodoc:
2
- class Engine < ::Rails::Engine #:nodoc:
3
- end
4
- end
@@ -1,21 +0,0 @@
1
- require "test_helper"
2
- require "active_record"
3
-
4
- class BoundMapperTest < TestCase
5
-
6
- def setup
7
- @bound_mapper = Valle::BoundMapper.new
8
- end
9
-
10
- def test_should_return_bound
11
- column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "")
12
- assert @bound_mapper.bound(column), "Bound for column '#{column.name}' not found"
13
- end
14
-
15
- def test_should_return_maximum_for_column_with_type_string
16
- column = ::ActiveRecord::ConnectionAdapters::Column.new("test_column", "", "string(255)")
17
- bound = @bound_mapper.bound(column)
18
-
19
- assert_equal 255, bound.maximum
20
- end
21
- end