Skip to content

Commit

Permalink
add all extension files to project
Browse files Browse the repository at this point in the history
  • Loading branch information
JediFreeman committed Feb 17, 2010
1 parent abc2a98 commit e01a957
Show file tree
Hide file tree
Showing 12 changed files with 373 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
== MIT License

Copyright (c) 2010, Benjamin J. Evans

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
62 changes: 62 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
= Radiant Validators

This [Radiant CMS][1] extension allows extension developers to easily override the validators built into Radiant's models. This is done
by adding new functions to the ActiveRecord class to clear validations, and remove validations based on a name. All built-in Radiant
model validations are cleared and redefined in this extension with names set to allow other extensions to remove them easily.

= INSTALLATION

1: Install the extension files

Automated Installation:
./script/extension install radiant_validators

Manual Installation:
cd ./vendor/extensions
git clone git://github.com/JediFreeman/Radiant-Validators-Extension.git

2: Restart the server

= HOW TO USE

To override a validator, it is pretty straight forward. Take a look at the example below that overrides the Page model slug format
validator to allow apostrophes.

1: In your extension lib directory, create an extender file for the model you wish to override (for example, to override the Page model,
create page_extender.rb) and add the following:

module PageExtender
def self.included(base)
base.class_eval {
# remove the existing validation for slug format
base.remove_validation :page_slug_format

# add a new validator with a slightly different regex to allow apostrophes
validates_format_of :slug, :with => %r{^([-_.A-Za-z0-9']*|/)$}, :message => 'invalid format', :name => :page_slug_format
}
end
end

2: In your main extension file activate method, include your extender on the Page model:

def activate
Page.send :include, PageExtender
end

3: Restart the server

= ADDITIONAL INFORMATION

To see a list of validator names, take a look in radiant_validators/app/models/*_validation_extender.rb files.

custom validator functions (defined with 'validate :function_name') are not in the scope of this extension, as those can already easily
be overridden by creating a new function in your extender.

You can verify the validators on a model by loading up the script/console and calling <Model>.validate (ie, Page.validate). You will get a list of validators and you should be able to see the :name setting for each one.

= QUESTIONS OR ISSUES

Please use the Issues panel on the [GitHub Project Page][2] to report any issues.

[1]: http://radiantcms.org/
[2]: http://github.com/JediFreeman/Radiant-Validators-Extension
136 changes: 136 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "radiant-radiant_validators-extension"
gem.summary = %Q{Radiant Validators Extension for Radiant CMS}
gem.description = %Q{Describe your extension here}
gem.email = "your email"
gem.homepage = "http://yourwebsite.com/radiant_validators"
gem.authors = ["Your Name"]
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
rescue LoadError
puts "Jeweler (or a dependency) not available. This is only required if you plan to package radiant_validators as a gem."
end

# In rails 1.2, plugins aren't available in the path until they're loaded.
# Check to see if the rspec plugin is installed first and require
# it if it is. If not, use the gem version.

# Determine where the RSpec plugin is by loading the boot
unless defined? RADIANT_ROOT
ENV["RAILS_ENV"] = "test"
case
when ENV["RADIANT_ENV_FILE"]
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
else
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
end
end

require 'rake'
require 'rake/rdoctask'
require 'rake/testtask'

rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
require 'spec/rake/spectask'
require 'cucumber'
require 'cucumber/rake/task'

# Cleanup the RADIANT_ROOT constant so specs will load the environment
Object.send(:remove_const, :RADIANT_ROOT)

extension_root = File.expand_path(File.dirname(__FILE__))

task :default => :spec
task :stats => "spec:statsetup"

desc "Run all specs in spec directory"
Spec::Rake::SpecTask.new(:spec) do |t|
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
t.spec_files = FileList['spec/**/*_spec.rb']
end

task :features => 'spec:integration'

namespace :spec do
desc "Run all specs in spec directory with RCov"
Spec::Rake::SpecTask.new(:rcov) do |t|
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
t.spec_files = FileList['spec/**/*_spec.rb']
t.rcov = true
t.rcov_opts = ['--exclude', 'spec', '--rails']
end

desc "Print Specdoc for all specs"
Spec::Rake::SpecTask.new(:doc) do |t|
t.spec_opts = ["--format", "specdoc", "--dry-run"]
t.spec_files = FileList['spec/**/*_spec.rb']
end

[:models, :controllers, :views, :helpers].each do |sub|
desc "Run the specs under spec/#{sub}"
Spec::Rake::SpecTask.new(sub) do |t|
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
end
end

desc "Run the Cucumber features"
Cucumber::Rake::Task.new(:integration) do |t|
t.fork = true
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
# t.feature_pattern = "#{extension_root}/features/**/*.feature"
t.profile = "default"
end

# Setup specs for stats
task :statsetup do
require 'code_statistics'
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
::STATS_DIRECTORIES << %w(View\ specs spec/views)
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
::CodeStatistics::TEST_TYPES << "Model specs"
::CodeStatistics::TEST_TYPES << "View specs"
::CodeStatistics::TEST_TYPES << "Controller specs"
::CodeStatistics::TEST_TYPES << "Helper specs"
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
end

namespace :db do
namespace :fixtures do
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
task :load => :environment do
require 'active_record/fixtures'
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
end
end
end
end
end

desc 'Generate documentation for the radiant_validators extension.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'RadiantValidatorsExtension'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('lib/**/*.rb')
end

# For extensions that are in transition
desc 'Test the radiant_validators extension.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end

# Load any custom rakefiles for extension
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
13 changes: 13 additions & 0 deletions app/models/layout_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'active_record_validation_extender'

module LayoutValidationExtender
def self.included(base)
base.class_eval {
base.clear_validations
validates_presence_of :name, :message => 'required', :name => :layout_name_presence
validates_uniqueness_of :name, :message => 'name already in use', :name => :layout_name_uniqueness
validates_length_of :name, :maximum => 100, :message => '{{count}}-character limit', :name => :layout_name_length
}

end
end
14 changes: 14 additions & 0 deletions app/models/page_part_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'active_record_validation_extender'

module PagePartValidationExtender
def self.included(base)
base.class_eval {
base.clear_validations
validates_presence_of :name, :message => 'required', :name => :page_part_name_presence
validates_length_of :name, :maximum => 100, :message => '{{count}}-character limit', :name => :page_part_name_length
validates_length_of :filter_id, :maximum => 25, :allow_nil => true, :message => '{{count}}-character limit', :name => :page_part_filter_id_length
validates_numericality_of :id, :page_id, :allow_nil => true, :only_integer => true, :message => 'must be a number', :name => :page_part_id_numericality
}

end
end
21 changes: 21 additions & 0 deletions app/models/page_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'active_record_validation_extender'

module PageValidationExtender
def self.included(base)
base.class_eval {
base.clear_validations
validates_presence_of :title, :slug, :breadcrumb, :status_id, :message => 'required', :name => :page_title_presence

validates_length_of :title, :maximum => 255, :message => '{{count}}-character limit', :name => :page_title_length
validates_length_of :slug, :maximum => 100, :message => '{{count}}-character limit', :name => :page_slug_length
validates_length_of :breadcrumb, :maximum => 160, :message => '{{count}}-character limit', :name => :page_breadcrumb_length
validates_format_of :slug, :with => %r{^([-_.A-Za-z0-9]*|/)$}, :message => 'invalid format', :name => :page_slug_format
validates_uniqueness_of :slug, :scope => :parent_id, :message => 'slug already in use for child of parent', :name => :page_slug_uniqueness
validates_numericality_of :id, :status_id, :parent_id, :allow_nil => true, :only_integer => true, :message => 'must be a number', :name => :page_numericality

# no need to set name for this, just override the valid_class_name function to replace this behavior
validate :valid_class_name
}

end
end
15 changes: 15 additions & 0 deletions app/models/snippet_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'active_record_validation_extender'

module SnippetValidationExtender
def self.included(base)
base.class_eval {
base.clear_validations
validates_presence_of :name, :message => 'required', :name => :snippet_name_presence
validates_length_of :name, :maximum => 100, :message => '{{count}}-character limit', :name => :snippet_name_length
validates_length_of :filter_id, :maximum => 25, :allow_nil => true, :message => '{{count}}-character limit', :name => :snippet_filter_id_length
validates_format_of :name, :with => %r{^\S*$}, :message => 'cannot contain spaces or tabs', :name => :snippet_name_format
validates_uniqueness_of :name, :message => 'name already in use', :name => :snippet_name_uniqueness
}

end
end
25 changes: 25 additions & 0 deletions app/models/user_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'active_record_validation_extender'

module UserValidationExtender
def self.included(base)
base.class_eval {
base.clear_validations
validates_uniqueness_of :login, :message => 'login already in use', :name => :user_login_uniqueness

validates_confirmation_of :password, :message => 'must match confirmation', :if => :confirm_password?, :name => :user_password_confirmation

validates_presence_of :name, :login, :message => 'required', :name => :user_name_login_presence
validates_presence_of :password, :password_confirmation, :message => 'required', :if => :new_record?, :name => :user_password_presence

validates_format_of :email, :message => 'invalid e-mail address', :allow_nil => true, :with => /^$|^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :name => :user_email_format

validates_length_of :name, :maximum => 100, :allow_nil => true, :message => '{{count}}-character limit', :name => :user_name_length
validates_length_of :login, :within => 3..40, :allow_nil => true, :too_long => '{{count}}-character limit', :too_short => '{{count}}-character minimum', :name => :user_login_length
validates_length_of :password, :within => 5..40, :allow_nil => true, :too_long => '{{count}}-character limit', :too_short => '{{count}}-character minimum', :if => :validate_length_of_password?, :name => :user_password_length
validates_length_of :email, :maximum => 255, :allow_nil => true, :message => '{{count}}-character limit', :name => :user_email_length

validates_numericality_of :id, :only_integer => true, :allow_nil => true, :message => 'must be a number', :name => :user_id_numericality
}

end
end
1 change: 1 addition & 0 deletions cucumber.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default: --format progress features --tags ~@proposed,~@in_progress
13 changes: 13 additions & 0 deletions lib/active_record_validation_extender.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module ActiveRecord
class Base
def self.clear_validations
@validate_callbacks = []
end
def self.remove_validation(sym)
@validate_callbacks.reject! {|validation| validation.options[:name] == sym}
end
def self.remove_validation_group(sym)
@validate_callbacks.reject! {|validation| validation.options[:group] == sym}
end
end
end
36 changes: 36 additions & 0 deletions lib/tasks/radiant_validators_extension_tasks.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace :radiant do
namespace :extensions do
namespace :radiant_validators do

desc "Runs the migration of the Radiant Validators extension"
task :migrate => :environment do
require 'radiant/extension_migrator'
if ENV["VERSION"]
RadiantValidatorsExtension.migrator.migrate(ENV["VERSION"].to_i)
else
RadiantValidatorsExtension.migrator.migrate
end
end

desc "Copies public assets of the Radiant Validators to the instance public/ directory."
task :update => :environment do
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
puts "Copying assets from RadiantValidatorsExtension"
Dir[RadiantValidatorsExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
path = file.sub(RadiantValidatorsExtension.root, '')
directory = File.dirname(path)
mkdir_p RAILS_ROOT + directory, :verbose => false
cp file, RAILS_ROOT + path, :verbose => false
end
unless RadiantValidatorsExtension.root.starts_with? RAILS_ROOT # don't need to copy vendored tasks
puts "Copying rake tasks from RadiantValidatorsExtension"
local_tasks_path = File.join(RAILS_ROOT, %w(lib tasks))
mkdir_p local_tasks_path, :verbose => false
Dir[File.join RadiantValidatorsExtension.root, %w(lib tasks *.rake)].each do |file|
cp file, local_tasks_path, :verbose => false
end
end
end
end
end
end
16 changes: 16 additions & 0 deletions radiant_validators_extension.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Uncomment this if you reference any of your controllers in activate
# require_dependency 'application_controller'

class RadiantValidatorsExtension < Radiant::Extension
version "1.0"
description "Extension to allow overriding of built-in validators in Radiant"
url "http://yourwebsite.com/radiant_validators"

def activate
Page.send :include, PageValidationExtender
Layout.send :include, LayoutValidationExtender
PagePart.send :include, PagePartValidationExtender
Snippet.send :include, SnippetValidationExtender
User.send :include, UserValidationExtender
end
end

0 comments on commit e01a957

Please sign in to comment.