├── .gitignore ├── .travis.yml ├── .yardopts ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── gemfiles ├── Gemfile.activemodel-3.0 └── Gemfile.activemodel-4.0 ├── lib ├── absolute_path_validator.rb ├── association_length_validator.rb ├── color_validator.rb ├── ean_validator.rb ├── email_validator.rb ├── ip_validator.rb ├── money_validator.rb ├── slug_validator.rb ├── uri_component_validator.rb ├── url_validator.rb ├── validates.rb └── validates │ └── version.rb ├── test ├── lib │ ├── absolute_path_validator_test.rb │ ├── color_validator_test.rb │ ├── ean_validator_test.rb │ ├── email_validator_test.rb │ ├── ip_validator_test.rb │ ├── money_validator_test.rb │ ├── slug_validator_test.rb │ ├── uri_component_validator_test.rb │ └── url_validator_test.rb ├── support │ └── model.rb └── test_helper.rb └── validates.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | doc/ 6 | .yardoc -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 1.9.3 4 | - 2.0.0 5 | - 2.1.0 6 | - 2.2.0 7 | - rbx 8 | - jruby 9 | gemfile: 10 | - Gemfile 11 | - gemfiles/Gemfile.activemodel-3.0 12 | - gemfiles/Gemfile.activemodel-4.0 13 | matrix: 14 | allow_failures: 15 | - rvm: rbx 16 | - rvm: jruby 17 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title "validates" 2 | --readme README.md 3 | - 4 | LICENSE 5 | CONTRIBUTING.md 6 | CHANGELOG.md 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.1.0 2 | 3 | * Moved InnValidator to [validates_russian](https://gthub.com/asiniy/validates_russian) gem 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We love pull requests. Here's a quick guide. 4 | 5 | Fork, then clone the repo: 6 | 7 | git clone git@github.com:your-username/validates.git 8 | 9 | Make sure the tests pass: 10 | 11 | bundle install 12 | rake 13 | 14 | Make your change. Add tests for your change. Make the tests pass: 15 | 16 | rake 17 | 18 | Push to your fork and [submit a pull request][pr]. 19 | 20 | [pr]: https://github.com/kaize/validates/compare/ 21 | 22 | At this point you're waiting on us. We like to at least comment on pull requests 23 | within three business days (and, typically, one business day). We may suggest 24 | some changes or improvements or alternatives. 25 | 26 | Some things that will increase the chance that your pull request is accepted: 27 | 28 | * Write tests. 29 | * Follow common [style guides][style]. 30 | * Write a [good commit message][commit]. 31 | * squash your commits before sending PR. 32 | 33 | [style]: https://github.com/thoughtbot/guides/tree/master/style 34 | [commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 35 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | gem 'rake' 6 | 7 | group :test do 8 | gem 'minitest', '~> 5' 9 | gem 'minitest-reporters' 10 | end 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2014 Mikhail Stolbov and kaize 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Validates [![Gem Version](https://badge.fury.io/rb/validates.png)](http://badge.fury.io/rb/validates) [![Build Status](https://travis-ci.org/kaize/validates.png)](https://travis-ci.org/kaize/validates) [![Code Climate](https://codeclimate.com/github/kaize/validates.png)](https://codeclimate.com/github/kaize/validates) 2 | 3 | Collection of useful custom validators for Rails applications, including: 4 | 5 | - AbsolutePathValidator 6 | - AssociationLengthValidator 7 | - ColorValidator 8 | - EanValidator ([EAN-8 & EAN-13](http://en.wikipedia.org/wiki/International_Article_Number_(EAN))) 9 | - EmailValidator 10 | - IpValidator 11 | - MoneyValidator 12 | - SlugValidator 13 | - UriComponentValidator 14 | - UrlValidator 15 | 16 | **Note** InnValidator and other Russian specific validators could be found at [validates_russian](https://github.com/asiniy/validates_russian) gem 17 | 18 | ## Installation 19 | 20 | Add this line to your application's Gemfile: 21 | 22 | ``` ruby 23 | gem 'validates' 24 | ``` 25 | 26 | Or install it yourself as: 27 | 28 | ``` bash 29 | $ gem install 'validates' 30 | ``` 31 | 32 | ## Usage 33 | 34 | For most of the validators you just want to add this line to your model: 35 | ``` ruby 36 | validates :attribute, : true 37 | ``` 38 | where `` is an underscored, lowercase form from the validator's name (see the examples section below). 39 | 40 | ### AssociationLengthValidator 41 | 42 | Because this is the successor of ActiveModel::Validations::LengthValidator 43 | validator, it inherits all the options of the latter, such as `:is`, `:minimum`, 44 | `:maximum`, etc. Another option, which you may be interested in is `:select` option, 45 | which allows you to filter the collection of the associated objects. 46 | 47 | ## Examples 48 | 49 | ``` ruby 50 | class User < ActiveRecord::Base 51 | validates :email, :email => true 52 | validates :site, :url => true, :allow_blank => true 53 | end 54 | 55 | class Company < ActiveRecord::Base 56 | # note AssociationLengthValidator is inherited from ActiveModel::Validations::LengthValidator 57 | # http://api.rubyonrails.org/classes/ActiveModel/Validations/LengthValidator.html 58 | # so you can easily use standard options like :is, :minimum, :maximum, etc. 59 | 60 | validates :employees, 61 | :association_length => { 62 | :minimum => 1, 63 | :select => ->(employee) { employee.name.in? ["Mike", "John"] } 64 | } 65 | 66 | validates :employees, :association_length => { :minimum => 1, :select => :employees_filter } 67 | 68 | def employees_filter(employees) 69 | employees.select { |employee| employee.name.in? ["Mike", "John"] } 70 | end 71 | end 72 | 73 | class Page < ActiveRecord::Base 74 | validates :slug, :slug => true 75 | end 76 | 77 | class Content < ActiveRecord::Base 78 | # Validates URI component. 79 | # URI component must be of the following type: 80 | # :ABS_URI, :REL_URI, :URI_REF, :ABS_URI_REF, :REL_URI_REF, :ESCAPED, :UNSAFE, :SCHEME, 81 | # :USERINFO, :HOST, :PORT, :OPAQUE, :REGISTRY, :ABS_PATH, :REL_PATH, :QUERY or :FRAGMENT. 82 | # These types are provided URI library. For more info see URI::DEFAULT_PARSER.regexp. 83 | 84 | validates :path, :uri_component => { :component => :ABS_PATH } 85 | end 86 | 87 | ``` 88 | 89 | ## Contributing 90 | 91 | Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details. 92 | 93 | ## Credits 94 | 95 | Originally written by Mikhail Stolbov. Maintained by kaize. 96 | 97 | Thank you to all our amazing [contributors](http://github.com/kaize/validates/contributors)! 98 | 99 | ## License 100 | 101 | validates is Copyright © 2012-2014 Mikhail Stolbov and kaize. It is free 102 | software, and may be redistributed under the terms specified in the LICENSE 103 | file. 104 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require 'rake/testtask' 3 | 4 | Rake::TestTask.new do |t| 5 | t.libs << "test" 6 | t.test_files = FileList['test/lib/*_test.rb'] 7 | t.verbose = true 8 | end 9 | 10 | task :default => :test 11 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.activemodel-3.0: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec path: '..' 4 | 5 | gem 'activemodel', '~>3.0' 6 | gem 'activesupport', '~>3.0' 7 | gem 'rake' 8 | gem 'minitest', '~> 5' 9 | gem 'minitest-reporters' 10 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.activemodel-4.0: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec path: '..' 4 | 5 | gem 'activemodel', '~>4.0' 6 | gem 'activesupport', '~>4.0' 7 | gem 'rake' 8 | gem 'minitest', '~> 5' 9 | gem 'minitest-reporters' 10 | -------------------------------------------------------------------------------- /lib/absolute_path_validator.rb: -------------------------------------------------------------------------------- 1 | class AbsolutePathValidator < ActiveModel::EachValidator 2 | class << self 3 | def valid?(value) 4 | Pathname.new(value).absolute? 5 | end 6 | end 7 | 8 | def validate_each(record, attribute, value) 9 | unless self.class.valid?(value) 10 | record.errors.add(attribute, :absolute_path, options.merge(value: value)) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/association_length_validator.rb: -------------------------------------------------------------------------------- 1 | class AssociationLengthValidator < ActiveModel::Validations::LengthValidator 2 | def validate_each(record, attribute, value) 3 | value = value.reject(&:marked_for_destruction?) 4 | value = select_items(record, value, options[:select]) if options[:select] 5 | 6 | super(record, attribute, value) 7 | end 8 | 9 | private 10 | 11 | def select_items(record, items, select_expr) 12 | case select_expr 13 | when Symbol, String 14 | if record.respond_to?(select_expr) 15 | record.send(select_expr, items) 16 | else 17 | raise ArgumentError, "Missing instance method #{record.class.name}##{select_expr}" 18 | end 19 | when Proc 20 | items.select(&select_expr) 21 | else 22 | items 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/color_validator.rb: -------------------------------------------------------------------------------- 1 | class ColorValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | unless value =~ /^[#]([a-f0-9]{3}|[a-f0-9]{6})$/ || COLORS.include?(value) 4 | record.errors.add(attribute, :color, options.merge(value: value)) 5 | end 6 | end 7 | 8 | # from W3C: http://www.w3.org/TR/css3-color/#svg-color 9 | COLORS = %w(aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen) 10 | end 11 | -------------------------------------------------------------------------------- /lib/ean_validator.rb: -------------------------------------------------------------------------------- 1 | class EanValidator < ActiveModel::EachValidator 2 | # http://en.wikipedia.org/wiki/International_Article_Number_(EAN) 3 | # EAN-8 & EAN-13 validator 4 | 5 | def validate_each(record, attribute, value) 6 | unless valid?(value) 7 | record.errors.add(attribute, :ean, options.merge(value: value)) 8 | end 9 | end 10 | 11 | private 12 | 13 | def valid?(ean) 14 | return false if ean.blank? 15 | return false unless ean =~ /^\d+$/ 16 | return false unless (8..13).include?(ean.length) 17 | return false unless calc_check_digit(ean) 18 | 19 | true 20 | end 21 | 22 | def calc_check_digit(ean) 23 | ean.rjust(13, "0".freeze).each_char.map.with_index { |char, i| char.to_i * EAN_CHECK_DIGIT13[i] }.reduce(:+) % 10 == 0 24 | end 25 | 26 | EAN_CHECK_DIGIT13 = [1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1] 27 | private_constant :EAN_CHECK_DIGIT13 28 | end 29 | -------------------------------------------------------------------------------- /lib/email_validator.rb: -------------------------------------------------------------------------------- 1 | class EmailValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | unless valid?(value) 4 | record.errors.add(attribute, :email, options.merge(value: value)) 5 | end 6 | end 7 | 8 | MAX_EMAIL_LENGTH = 254 9 | MAX_DOMAIN_LENGTH = 255 10 | MAX_DOMAIN_PART_LENGTH = 64 11 | MAX_USER_LENGTH = 64 12 | LOCAL_ALLOWED_CHARS = '(?:[a-z0-9A-Z\!\#\$\%\&\'\*\-\/\=\?\+\-\^\_\`\{\|\}\~]|(? MAX_EMAIL_LENGTH 27 | return false if domain.length > MAX_DOMAIN_LENGTH || local.length > MAX_USER_LENGTH 28 | return false if !email_domain_syntax_valid?(domain) || !email_local_syntax_valid?(local) 29 | 30 | true 31 | end 32 | 33 | def email_domain_syntax_valid?(domain) 34 | parts = domain.reverse.downcase.gsub(/(?:^\[(.+)\]$)/,'\1').split('.', -1) 35 | 36 | return false if parts.size == 1 && options[:reject_one_level_domain] 37 | return false unless parts.all? { |part| part =~ /^(?!\-)[[:alnum:]\-]+(?<@iana.org', 130 | 'first(middle)last@iana.org' 131 | ] 132 | 133 | Model.validates :field, email: true 134 | 135 | invalid_emails.each do |email| 136 | model = Model.new 137 | model.field = email 138 | 139 | refute model.valid?, "#{email} not valid" 140 | end 141 | end 142 | end 143 | -------------------------------------------------------------------------------- /test/lib/ip_validator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class IpValidatorTest < ValidatorTest 4 | def test_valid 5 | valid_ips = %w( 6 | 21.189.63.11 7 | 192.168.0.1 8 | 127.0.0.1 9 | FE80:0000:0000:0000:0202:B3FF:FE1E:8329 10 | ) 11 | 12 | Model.validates :field, ip: true 13 | 14 | valid_ips.each do |ip| 15 | model = Model.new 16 | model.field = ip 17 | 18 | assert model.valid?, "#{ip} not valid" 19 | end 20 | end 21 | 22 | def test_invalid 23 | invalid_ips = %w( 24 | epic 25 | 123.18.18 26 | 127.0.0. 27 | 127.0.0.1.0 28 | ) 29 | 30 | Model.validates :field, ip: true 31 | 32 | invalid_ips.each do |ip| 33 | model = Model.new 34 | model.field = ip 35 | 36 | refute model.valid?, "#{ip} not valid" 37 | end 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /test/lib/money_validator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class MoneyValidatorTest < ValidatorTest 4 | 5 | def test_valid 6 | valid_money_count = %w( 7 | 100 8 | 1000.00 9 | 1456 10 | 5 11 | 9000.00 12 | ) 13 | 14 | Model.validates :field, money: true 15 | 16 | valid_money_count.each do |money_count| 17 | model = Model.new 18 | model.field = money_count 19 | 20 | assert model.valid?, "#{money_count} not valid" 21 | end 22 | end 23 | 24 | def test_invalid 25 | invalid_money_cost = %w( 26 | orange-duck 27 | a11111 28 | 11111a 29 | 1234a5678 30 | ).push('', ' ', nil, {}, []) 31 | 32 | Model.validates :field, money: true 33 | 34 | invalid_money_cost.each do |money_cost| 35 | model = Model.new 36 | model.field = money_cost 37 | 38 | refute model.valid?, "#{money_cost} not valid" 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/lib/slug_validator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SlugValidatorTest < ValidatorTest 4 | 5 | def test_valid 6 | valid_slugs = %w( 7 | home 8 | global-news 9 | global_news 10 | new-2014-year 11 | ) 12 | 13 | Model.validates :field, slug: true 14 | 15 | valid_slugs.each do |slug| 16 | model = Model.new 17 | model.field = slug 18 | 19 | assert model.valid?, "#{slug} not valid" 20 | end 21 | end 22 | 23 | def test_invalid 24 | invalid_slugs = %w( 25 | home? 26 | hello,world 27 | new/page 28 | !all'stars 29 | hello? 30 | ) 31 | 32 | Model.validates :field, slug: true 33 | 34 | invalid_slugs.each do |slug| 35 | model = Model.new 36 | model.field = slug 37 | 38 | refute model.valid?, "#{slug} not valid" 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/lib/uri_component_validator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UriComponentValidatorTest < ValidatorTest 4 | 5 | def test_valid 6 | Model.validates :field, uri_component: { component: :ABS_PATH } 7 | model = Model.new 8 | model.field = '/some/path' 9 | 10 | assert model.valid? 11 | end 12 | 13 | def test_invalid 14 | Model.validates :field, uri_component: { component: :ABS_PATH } 15 | invalid_paths = ['some/path', '/with/space path'] 16 | 17 | invalid_paths.each do |path| 18 | model = Model.new 19 | model.field = path 20 | refute model.valid? 21 | end 22 | end 23 | 24 | def test_check_arguments 25 | assert_raises(ArgumentError) do 26 | Model.validates :field, uri_component: { component: :WRONG } 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/lib/url_validator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UrlValidatorTest < ValidatorTest 4 | 5 | def test_valid 6 | valid_urls = %w{ 7 | http://vk.com 8 | http://www.mail.ru/secret 9 | http://github.com/ 10 | http://odesk.com/query=ruby+rails 11 | http://192.168.0.1 12 | http://asiniy.ru 13 | https://google.com 14 | https://127.0.0.1 15 | } 16 | 17 | Model.validates :field, url: true 18 | 19 | valid_urls.each do |url| 20 | model = Model.new 21 | model.field = url 22 | assert model.valid?, "#{url} is not valid" 23 | end 24 | end 25 | 26 | def test_invalid 27 | invalid_urls = %w{ 28 | htt://yandex.ru 29 | httpns 30 | zzzz-mail 31 | 12345678 32 | /1https://vk.com 33 | }.push('', ' ', nil) 34 | 35 | Model.validates :field, url: true 36 | 37 | invalid_urls.each do |url| 38 | model = Model.new 39 | model.field = url 40 | refute model.valid?, "#{url} is not valid" 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/support/model.rb: -------------------------------------------------------------------------------- 1 | class Model 2 | include ActiveModel::Validations 3 | 4 | attr_accessor :field 5 | end 6 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler.require 3 | 4 | require 'minitest/autorun' 5 | 6 | # reporters doesn't work with AS < 4 (see https://travis-ci.org/kaize/validates/jobs/28579079) 7 | if defined?(ActiveSupport::VERSION) && ActiveSupport::VERSION::MAJOR >= 4 8 | require "minitest/reporters" 9 | Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(:color => true)] 10 | end 11 | 12 | Dir[File.dirname(__FILE__) + '/support/*.rb'].each{ |file| require file } 13 | 14 | class ValidatorTest < Minitest::Test 15 | 16 | def teardown 17 | Model.reset_callbacks(:validate) 18 | end 19 | 20 | end 21 | -------------------------------------------------------------------------------- /validates.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "validates/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "validates" 7 | s.version = Validates::VERSION 8 | s.authors = ["Mikhail Stolbov","Anton Taraev","Konstantin Kosmatov","Andrey Subbota"] 9 | s.email = ["mstolbov@gmail.com","anti191@gmail.com","key@kosmatov.su","subbota@gmail.com"] 10 | s.homepage = "http://github.com/kaize/validates" 11 | s.summary = %q{Collection of useful custom validators for Rails applications} 12 | s.description = %q{validates provides a set of commonly required validators (such as Email, Url, etc.) for Rails applications} 13 | 14 | s.rubyforge_project = "validates" 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | 20 | s.require_paths = ["lib"] 21 | 22 | s.rdoc_options = %w(--line-numbers --inline-source --title validates --main README.md) 23 | s.extra_rdoc_files = %w(README.md LICENSE CONTRIBUTING.md CHANGELOG.md) 24 | 25 | s.add_dependency "activemodel", [">= 3.0.0"] 26 | s.add_dependency "activesupport", [">= 3.0.0"] 27 | end 28 | --------------------------------------------------------------------------------