aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb34
-rw-r--r--actionpack/lib/action_view/locale/en.yml3
-rw-r--r--actionpack/lib/action_view/render/rendering.rb5
-rw-r--r--actionpack/lib/action_view/template/error.rb2
-rw-r--r--actionpack/lib/action_view/template/handlers/builder.rb2
-rw-r--r--actionpack/lib/action_view/template/template.rb119
-rw-r--r--actionpack/lib/action_view/template/text.rb29
-rw-r--r--actionpack/lib/action_view/test_case.rb125
8 files changed, 215 insertions, 104 deletions
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 332743d55b..8a7a870b99 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -26,8 +26,10 @@ module ActionView
# 47 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs # => [2..29] days
# 29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 1 month
# 59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec # => [2..12] months
- # 1 yr <-> 2 yrs minus 1 secs # => about 1 year
- # 2 yrs <-> max time or date # => over [2..X] years
+ # 1 yr <-> 1 yr, 3 months # => about 1 year
+ # 1 yr, 3 months <-> 1 yr, 9 months # => over 1 year
+ # 1 yr, 9 months <-> 2 yr minus 1 sec # => almost 2 years
+ # 2 yrs <-> max time or date # => (same rules as 1 yr)
#
# With <tt>include_seconds</tt> = true and the difference < 1 minute 29 seconds:
# 0-4 secs # => less than 5 seconds
@@ -43,17 +45,18 @@ module ActionView
# distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
# distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
# distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
- # distance_of_time_in_words(from_time, 3.years.from_now) # => over 3 years
+ # distance_of_time_in_words(from_time, 3.years.from_now) # => about 3 years
# distance_of_time_in_words(from_time, from_time + 60.hours) # => about 3 days
# distance_of_time_in_words(from_time, from_time + 45.seconds, true) # => less than a minute
# distance_of_time_in_words(from_time, from_time - 45.seconds, true) # => less than a minute
# distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
# distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 year
- # distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => over 4 years
+ # distance_of_time_in_words(from_time, from_time + 3.years + 6.months) # => over 3 years
+ # distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
#
# to_time = Time.now + 6.years + 19.days
- # distance_of_time_in_words(from_time, to_time, true) # => over 6 years
- # distance_of_time_in_words(to_time, from_time, true) # => over 6 years
+ # distance_of_time_in_words(from_time, to_time, true) # => about 6 years
+ # distance_of_time_in_words(to_time, from_time, true) # => about 6 years
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
@@ -81,12 +84,21 @@ module ActionView
when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
when 45..89 then locale.t :about_x_hours, :count => 1
when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
- when 1440..2879 then locale.t :x_days, :count => 1
- when 2880..43199 then locale.t :x_days, :count => (distance_in_minutes / 1440).round
+ when 1440..2529 then locale.t :x_days, :count => 1
+ when 2530..43199 then locale.t :x_days, :count => (distance_in_minutes.to_f / 1440.0).round
when 43200..86399 then locale.t :about_x_months, :count => 1
- when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes / 43200).round
- when 525600..1051199 then locale.t :about_x_years, :count => 1
- else locale.t :over_x_years, :count => (distance_in_minutes / 525600).round
+ when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
+ else
+ distance_in_years = distance_in_minutes / 525600
+ minute_offset_for_leap_year = (distance_in_years / 4) * 1440
+ remainder = ((distance_in_minutes - minute_offset_for_leap_year) % 525600)
+ if remainder < 131400
+ locale.t(:about_x_years, :count => distance_in_years)
+ elsif remainder < 394200
+ locale.t(:over_x_years, :count => distance_in_years)
+ else
+ locale.t(:almost_x_years, :count => distance_in_years + 1)
+ end
end
end
end
diff --git a/actionpack/lib/action_view/locale/en.yml b/actionpack/lib/action_view/locale/en.yml
index c82cd07ec2..84d94fd700 100644
--- a/actionpack/lib/action_view/locale/en.yml
+++ b/actionpack/lib/action_view/locale/en.yml
@@ -91,6 +91,9 @@
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+ almost_x_years:
+ one: "almost 1 year"
+ other: "almost {{count}} years"
prompts:
year: "Year"
month: "Month"
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index b0b75918b7..0cab035ede 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -89,6 +89,7 @@ module ActionView
def _render_text(text, layout, options)
text = layout.render(self, options[:locals]) { text } if layout
+ text
end
# This is the API to render a ViewContext's template from a controller.
@@ -105,7 +106,7 @@ module ActionView
def _render_template(template, layout = nil, options = {}, partial = nil)
logger && logger.info do
- msg = "Rendering #{template.identifier}"
+ msg = "Rendering #{template.inspect}"
msg << " (#{options[:status]})" if options[:status]
msg
end
@@ -123,7 +124,7 @@ module ActionView
if layout
@_layout = layout.identifier
- logger.info("Rendering template within #{layout.identifier}") if logger
+ logger.info("Rendering template within #{layout.inspect}") if logger
content = layout.render(self, locals) {|*name| _layout_for(*name) }
end
content
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index 6e5093c5bd..aa21606f76 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -32,7 +32,7 @@ module ActionView
def sub_template_message
if @sub_templates
"Trace of template inclusion: " +
- @sub_templates.collect { |template| template.identifier }.join(", ")
+ @sub_templates.collect { |template| template.inspect }.join(", ")
else
""
end
diff --git a/actionpack/lib/action_view/template/handlers/builder.rb b/actionpack/lib/action_view/template/handlers/builder.rb
index ba0d17b5af..5f381f7bf0 100644
--- a/actionpack/lib/action_view/template/handlers/builder.rb
+++ b/actionpack/lib/action_view/template/handlers/builder.rb
@@ -6,7 +6,7 @@ module ActionView
self.default_format = Mime::XML
def compile(template)
- require 'active_support/vendor/builder'
+ require 'builder'
"xml = ::Builder::XmlMarkup.new(:indent => 2);" +
"self.output_buffer = xml.target!;" +
template.source +
diff --git a/actionpack/lib/action_view/template/template.rb b/actionpack/lib/action_view/template/template.rb
index 80c1bab7d5..0f64c23649 100644
--- a/actionpack/lib/action_view/template/template.rb
+++ b/actionpack/lib/action_view/template/template.rb
@@ -8,7 +8,7 @@ module ActionView
class Template
extend TemplateHandlers
attr_reader :source, :identifier, :handler, :mime_type, :formats, :details
-
+
def initialize(source, identifier, handler, details)
@source = source
@identifier = identifier
@@ -25,7 +25,7 @@ module ActionView
@formats << :html if format == :js
@details[:formats] = Array.wrap(format.to_sym)
end
-
+
def render(view, locals, &block)
ActiveSupport::Orchestra.instrument(:render_template, :identifier => identifier) do
method_name = compile(locals, view)
@@ -39,7 +39,7 @@ module ActionView
raise TemplateError.new(self, view.assigns, e)
end
end
-
+
# TODO: Figure out how to abstract this
def variable_name
@variable_name ||= identifier[%r'_?(\w+)(\.\w+)*$', 1].to_sym
@@ -49,76 +49,83 @@ module ActionView
def counter_name
@counter_name ||= "#{variable_name}_counter".to_sym
end
-
+
# TODO: kill hax
def partial?
@details[:partial]
end
- private
+ def inspect
+ if defined?(Rails.root)
+ identifier.sub("#{Rails.root}/", '')
+ else
+ identifier
+ end
+ end
- def compile(locals, view)
- method_name = build_method_name(locals)
-
- return method_name if view.respond_to?(method_name)
-
- locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join
+ private
+ def compile(locals, view)
+ method_name = build_method_name(locals)
- code = @handler.call(self)
- if code.sub!(/\A(#.*coding.*)\n/, '')
- encoding_comment = $1
- elsif defined?(Encoding) && Encoding.respond_to?(:default_external)
- encoding_comment = "#coding:#{Encoding.default_external}"
- end
+ return method_name if view.respond_to?(method_name)
- source = <<-end_src
- def #{method_name}(local_assigns)
- old_output_buffer = output_buffer;#{locals_code};#{code}
- ensure
- self.output_buffer = old_output_buffer
- end
- end_src
+ locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join
- if encoding_comment
- source = "#{encoding_comment}\n#{source}"
- line = -1
- else
- line = 0
- end
+ code = @handler.call(self)
+ if code.sub!(/\A(#.*coding.*)\n/, '')
+ encoding_comment = $1
+ elsif defined?(Encoding) && Encoding.respond_to?(:default_external)
+ encoding_comment = "#coding:#{Encoding.default_external}"
+ end
- begin
- ActionView::CompiledTemplates.module_eval(source, identifier, line)
- method_name
- rescue Exception => e # errors from template code
- if logger = (view && view.logger)
- logger.debug "ERROR: compiling #{method_name} RAISED #{e}"
- logger.debug "Function body: #{source}"
- logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ source = <<-end_src
+ def #{method_name}(local_assigns)
+ old_output_buffer = output_buffer;#{locals_code};#{code}
+ ensure
+ self.output_buffer = old_output_buffer
+ end
+ end_src
+
+ if encoding_comment
+ source = "#{encoding_comment}\n#{source}"
+ line = -1
+ else
+ line = 0
end
- raise ActionView::TemplateError.new(self, {}, e)
+ begin
+ ActionView::CompiledTemplates.module_eval(source, identifier, line)
+ method_name
+ rescue Exception => e # errors from template code
+ if logger = (view && view.logger)
+ logger.debug "ERROR: compiling #{method_name} RAISED #{e}"
+ logger.debug "Function body: #{source}"
+ logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ end
+
+ raise ActionView::TemplateError.new(self, {}, e)
+ end
end
- end
- class LocalsKey
- @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }
+ class LocalsKey
+ @hash_keys = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }
- def self.get(*locals)
- @hash_keys[*locals] ||= new(klass, format, locale)
- end
+ def self.get(*locals)
+ @hash_keys[*locals] ||= new(klass, format, locale)
+ end
- attr_accessor :hash
- def initialize(klass, format, locale)
- @hash = locals.hash
- end
+ attr_accessor :hash
+ def initialize(klass, format, locale)
+ @hash = locals.hash
+ end
- alias_method :eql?, :equal?
- end
+ alias_method :eql?, :equal?
+ end
- def build_method_name(locals)
- # TODO: is locals.keys.hash reliably the same?
- @method_names[locals.keys.hash] ||=
- "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
- end
+ def build_method_name(locals)
+ # TODO: is locals.keys.hash reliably the same?
+ @method_names[locals.keys.hash] ||=
+ "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
+ end
end
end
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index 9f12e5e0a8..f7d0df5ba0 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -1,6 +1,5 @@
module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
-
def initialize(string, content_type = Mime[:html])
super(string.to_s)
@content_type = Mime[content_type] || content_type
@@ -10,14 +9,28 @@ module ActionView #:nodoc:
{:formats => [@content_type.to_sym]}
end
- def identifier() self end
-
- def render(*) self end
-
- def mime_type() @content_type end
+ def identifier
+ self
+ end
+
+ def inspect
+ 'inline template'
+ end
+
+ def render(*args)
+ self
+ end
- def formats() [mime_type] end
+ def mime_type
+ @content_type
+ end
- def partial?() false end
+ def formats
+ [mime_type]
+ end
+
+ def partial?
+ false
+ end
end
end
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index c2ccd1d3a5..441f462bc9 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -1,4 +1,5 @@
require 'active_support/test_case'
+require 'action_controller/testing/test_case'
module ActionView
class Base
@@ -23,12 +24,52 @@ module ActionView
end
class TestCase < ActiveSupport::TestCase
+ class TestController < ActionController::Base
+ attr_accessor :request, :response, :params
+
+ def self.controller_path
+ ''
+ end
+
+ def initialize
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ @params = {}
+ end
+ end
+
include ActionDispatch::Assertions
include ActionController::TestProcess
include ActionView::Context
+ include ActionController::PolymorphicRoutes
+ include ActionController::RecordIdentifier
+
+ include ActionView::Helpers
+ include ActionController::Helpers
+
class_inheritable_accessor :helper_class
- @@helper_class = nil
+ attr_accessor :controller, :output_buffer, :rendered
+
+ setup :setup_with_controller
+ def setup_with_controller
+ @controller = TestController.new
+ @output_buffer = ''
+ @rendered = ''
+
+ self.class.send(:include_helper_modules!)
+ make_test_case_available_to_view!
+ end
+
+ def render(options = {}, local_assigns = {}, &block)
+ @rendered << output = _view.render(options, local_assigns, &block)
+ output
+ end
+
+ def protect_against_forgery?
+ false
+ end
class << self
def tests(helper_class)
@@ -48,41 +89,75 @@ module ActionView
rescue NameError
nil
end
- end
- include ActionView::Helpers
- include ActionController::PolymorphicRoutes
- include ActionController::RecordIdentifier
-
- setup :setup_with_helper_class
-
- def setup_with_helper_class
- if helper_class && !self.class.ancestors.include?(helper_class)
- self.class.send(:include, helper_class)
+ def helper_method(*methods)
+ # Almost a duplicate from ActionController::Helpers
+ methods.flatten.each do |method|
+ _helpers.module_eval <<-end_eval
+ def #{method}(*args, &block) # def current_user(*args, &block)
+ _test_case.send(%(#{method}), *args, &block) # test_case.send(%(current_user), *args, &block)
+ end # end
+ end_eval
+ end
end
- self.output_buffer = ''
+ private
+ def include_helper_modules!
+ helper(helper_class) if helper_class
+ include _helpers
+ end
end
- class TestController < ActionController::Base
- attr_accessor :request, :response, :params
+ private
+ def make_test_case_available_to_view!
+ test_case_instance = self
+ _helpers.module_eval do
+ define_method(:_test_case) { test_case_instance }
+ private :_test_case
+ end
+ end
- def initialize
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
+ def _view
+ view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
+ view.class.send :include, _helpers
+ view
+ end
- @params = {}
+ # Support the selector assertions
+ #
+ # Need to experiment if this priority is the best one: rendered => output_buffer
+ def response_from_page_or_rjs
+ HTML::Document.new(rendered.blank? ? output_buffer : rendered).root
+ end
+
+ EXCLUDE_IVARS = %w{
+ @output_buffer
+ @fixture_cache
+ @method_name
+ @_result
+ @loaded_fixtures
+ @test_passed
+ @view
+ }
+
+ def _instance_variables
+ instance_variables - EXCLUDE_IVARS
end
- end
- protected
- attr_accessor :output_buffer
+ def _assigns
+ _instance_variables.inject({}) do |hash, var|
+ name = var[1..-1].to_sym
+ hash[name] = instance_variable_get(var)
+ hash
+ end
+ end
- private
def method_missing(selector, *args)
- controller = TestController.new
- return controller.__send__(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
- super
+ if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
+ @controller.__send__(selector, *args)
+ else
+ super
+ end
end
end
end