Skip to content

Commit

Permalink
Validations handler
Browse files Browse the repository at this point in the history
This adds links to the 'validates' handler.

It links to the docs for the standard links and custom types can be added by calling
YARD::Handlers::Ruby::ActiveRecord::Validate.add_validation_type( type, link )
  • Loading branch information
nathanstitt committed Mar 26, 2014
1 parent 7fe2708 commit f680f6c
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 22 deletions.
1 change: 1 addition & 0 deletions lib/yard-activerecord/fields/field_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class FieldHandler < YARD::Handlers::Ruby::MethodHandler
handles method_call(:integer)
handles method_call(:float)
handles method_call(:boolean)
handles method_call(:decimal)
handles method_call(:timestamp)
handles method_call(:datetime)
handles method_call(:date)
Expand Down
56 changes: 47 additions & 9 deletions lib/yard-activerecord/validations/validates_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,41 @@

module YARD::Handlers::Ruby::ActiveRecord::Validate

# Links with a value of nil will be link to
# the Rails Validations guide.
# Other projects can add to the
STANDARD_LINKS = [
:acceptance,
:validates_associated,
:confirmation,
:exclusion,
:format,
:inclusion,
:length,
:numericality,
:presence,
:absence,
:uniqueness,
:validates_with,
:validates_each
]

def self.add_validation_type( type, link )
@custom_types ||= {}
@custom_types[type.to_sym] = link
end

def self.link_for_validation( type )
type = type.downcase.to_sym
if STANDARD_LINKS.include?( type )
"http://edgeguides.rubyonrails.org/active_record_validations.html##{type}"
elsif @custom_types && link = @custom_types[ type ]
link
else
nil
end
end

# Define validations tag for later use
YARD::Tags::Library.define_tag("Validations", :validates )

Expand All @@ -15,23 +50,22 @@ module YARD::Handlers::Ruby::ActiveRecord::Validate
class ValidatesHandler < YARD::Handlers::Ruby::MethodHandler
namespace_only
handles method_call(:validates)

def process

validations = {}
attributes = []
conditions = []
conditions = {}

# Read each parameter to the statement and parse out
# it's type and intent
statement.parameters(false).compact.map do |param|
# list types are options
if param.type == :list
param.each do | n |
kw = n.jump(:ident, :kw, :tstring_content ).source
kw = n.jump(:label, :symbol_literal ).source.gsub(/:/,'')
# if/unless are conditions that apply to all the validations
if kw == 'if' || kw=='unless'
conditions = [kw, n.children.last.source ]
if ['if','unless','on'].include?(kw)
conditions[ kw ] = n.children.last.source
else # otherwise it's type specific
opts = n.jump(:hash)
value = ( opts != n ) ? opts.source : nil
Expand All @@ -50,6 +84,10 @@ def process
attributes.each do | attribute |
method_definition = namespace.instance_attributes[attribute.to_sym] || {}
method = method_definition[:read]
if ! method
meths = namespace.meths(:all => true)
method = meths.find {|m| m.name == attribute.to_sym }
end
# If the method isn't defined yet, go ahead and create one
if ! method
method = YARD::CodeObjects::MethodObject.new(namespace, attribute )
Expand All @@ -60,13 +98,13 @@ def process
namespace.instance_attributes[attribute.to_sym] = method_definition
end
tag = YARD::Tags::OptionTag.new(:validates, '', conditions ) #, [] )
tag.types = []
validations.each{ |arg,options|
tag.types << ( arg.capitalize + ( options ? "(#{options})" : '' ) )
tag.types = {} #[]
validations.each{ |arg,options|
tag.types[ arg ] = options
}
method.docstring.add_tag tag
end

end
end

Expand Down
11 changes: 9 additions & 2 deletions templates/default/tags/html/validations.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<p class="tag_title">Validations<% if @condition %> (<i><%= @condition %></i> )<% end %>:</p>
<ul class="validations">
<% for tag in @tags %>
<% for type in tag.types %>
<li><%= type %></li>
<% tag.types.each do | type, options | %>
<li>
<% if link = YARD::Handlers::Ruby::ActiveRecord::Validate.link_for_validation( type ) %>
<%= linkify(link, type.capitalize ) %>
<% else %>
<%= type.capitalize %>
<% end %>
<% if options %> (<%= options %>) <% end %>
</li>
<% end %>
<% end %>
</ul>
17 changes: 6 additions & 11 deletions templates/default/tags/setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ def init
def validates
all_tags = object.tags(:validates)
out = ''
conditions = all_tags.map{| tag | tag.pair.join }.uniq.compact
conditions = all_tags.map{| tag | tag.pair.to_s }.uniq.compact
conditions.each do | condition |
@tags = all_tags.select{|tag| tag.pair.join == condition }
unless condition.empty?
options = @tags.first.pair
condition = options.first.capitalize + ' '
if options.last =~/^:/ # it's a symbol, convert to link
condition << linkify(options.last.gsub(/^:/,'#'))
else
condition << options.last
end
@tags = all_tags.select{|tag| tag.pair.to_s == condition }
condition = @tags.first.pair.map do | type, check |
check = linkify( check.gsub(/^:/,'#') ) if check =~/^:/ # it's a symbol, convert to link
"#{type} => #{check}"
end
@condition = condition.empty? ? nil : condition
@condition = condition.empty? ? nil : condition.join(',')
out << erb( :validations )
end
out
Expand Down

0 comments on commit f680f6c

Please sign in to comment.