diff options
143 files changed, 2146 insertions, 1026 deletions
@@ -1,97 +1,98 @@ -source "http://rubygems.org" +source 'https://rubygems.org' gemspec if ENV['AREL'] - gem "arel", :path => ENV['AREL'] + gem 'arel', :path => ENV['AREL'] else - gem "arel", :git => "git://github.com/rails/arel" + gem 'arel', :git => 'git://github.com/rails/arel' end -gem "bcrypt-ruby", "~> 3.0.0" -gem "jquery-rails" +gem 'bcrypt-ruby', '~> 3.0.0' +gem 'jquery-rails' if ENV['JOURNEY'] - gem "journey", :path => ENV['JOURNEY'] + gem 'journey', :path => ENV['JOURNEY'] else - gem "journey", :git => "git://github.com/rails/journey" + gem 'journey', :git => 'git://github.com/rails/journey' end # This needs to be with require false to avoid # it being automatically loaded by sprockets -gem "uglifier", ">= 1.0.3", :require => false +gem 'uglifier', '>= 1.0.3', :require => false -gem "rake", ">= 0.8.7" -gem "mocha", ">= 0.9.8" +gem 'rake', '>= 0.8.7' +gem 'mocha', '>= 0.9.8' group :doc do - gem "rdoc", "~> 3.4" - gem "sdoc", "~> 0.3" - gem "RedCloth", "~> 4.2" if RUBY_VERSION < "1.9.3" - gem "w3c_validators" + gem 'rdoc', '~> 3.4' + # The current sdoc cannot generate GitHub links due + # to a bug, but the PR that fixes it has been there + # for some weeks unapplied. As a temporary solution + # this is our own fork with the fix. + gem 'sdoc', :git => 'git://github.com/fxn/sdoc.git' + gem 'RedCloth', '~> 4.2' if RUBY_VERSION < '1.9.3' + gem 'w3c_validators' end # AS -gem "memcache-client", ">= 1.8.5" +gem 'memcache-client', '>= 1.8.5' platforms :mri_18 do - gem "system_timer" - gem "json" + gem 'system_timer' + gem 'json' end # Add your own local bundler stuff -instance_eval File.read ".Gemfile" if File.exists? ".Gemfile" +instance_eval File.read '.Gemfile' if File.exists? '.Gemfile' platforms :mri do group :test do - gem "ruby-prof" if RUBY_VERSION < "1.9.3" + gem 'ruby-prof' if RUBY_VERSION < '1.9.3' end end platforms :ruby do - if ENV["RB_FSEVENT"] - gem "rb-fsevent" - end - gem "json" - gem "yajl-ruby" - gem "nokogiri", ">= 1.4.5" + gem 'json' + gem 'yajl-ruby' + gem 'nokogiri', '>= 1.4.5' # AR - gem "sqlite3", "~> 1.3.5" + gem 'sqlite3', '~> 1.3.5' group :db do - gem "pg", ">= 0.11.0" - gem "mysql", ">= 2.8.1" - gem "mysql2", ">= 0.3.10" + gem 'pg', '>= 0.11.0' + gem 'mysql', '>= 2.8.1' + gem 'mysql2', '>= 0.3.10' end end platforms :jruby do - gem "json" - gem "activerecord-jdbcsqlite3-adapter", ">= 1.2.0" + gem 'json' + gem 'activerecord-jdbcsqlite3-adapter', '>= 1.2.0' # This is needed by now to let tests work on JRuby # TODO: When the JRuby guys merge jruby-openssl in # jruby this will be removed - gem "jruby-openssl" + gem 'jruby-openssl' group :db do - gem "activerecord-jdbcmysql-adapter", ">= 1.2.0" - gem "activerecord-jdbcpostgresql-adapter", ">= 1.2.0" + gem 'activerecord-jdbcmysql-adapter', '>= 1.2.0' + gem 'activerecord-jdbcpostgresql-adapter', '>= 1.2.0' end end # gems that are necessary for ActiveRecord tests with Oracle database if ENV['ORACLE_ENHANCED_PATH'] || ENV['ORACLE_ENHANCED'] platforms :ruby do - gem "ruby-oci8", ">= 2.0.4" + gem 'ruby-oci8', '>= 2.0.4' end if ENV['ORACLE_ENHANCED_PATH'] - gem "activerecord-oracle_enhanced-adapter", :path => ENV['ORACLE_ENHANCED_PATH'] + gem 'activerecord-oracle_enhanced-adapter', :path => ENV['ORACLE_ENHANCED_PATH'] else - gem "activerecord-oracle_enhanced-adapter", :git => "git://github.com/rsim/oracle-enhanced.git" + gem 'activerecord-oracle_enhanced-adapter', :git => 'git://github.com/rsim/oracle-enhanced.git' end end # A gem necessary for ActiveRecord tests with IBM DB -gem "ibm_db" if ENV['IBM_DB'] +gem 'ibm_db' if ENV['IBM_DB'] diff --git a/README.rdoc b/README.rdoc index 0def4e5d12..8844c74175 100644 --- a/README.rdoc +++ b/README.rdoc @@ -67,7 +67,9 @@ We encourage you to contribute to Ruby on Rails! Please check out the {Contribut guide}[http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how to proceed. {Join us}[http://contributors.rubyonrails.org]! -== Travis Build Status {<img src="https://secure.travis-ci.org/rails/rails.png"/>}[http://travis-ci.org/rails/rails] +== Build Status {<img src="https://secure.travis-ci.org/rails/rails.png"/>}[http://travis-ci.org/rails/rails] + +== Dependency Status {<img src="https://gemnasium.com/rails/rails.png?travis"/>}[https://gemnasium.com/rails/rails] == License diff --git a/RELEASING_RAILS.rdoc b/RELEASING_RAILS.rdoc index 9f25adeccc..7bad1d01b8 100644 --- a/RELEASING_RAILS.rdoc +++ b/RELEASING_RAILS.rdoc @@ -215,7 +215,7 @@ and generates and publishes stable docs if a new stable tag is detected. The hook unfortunately is not invoked by tag pushing, so once the new stable tag has been pushed to origin, please run - curl -X POST -d '' http://rails-hooks.hashref.com/rails-master-hook + rake publish_docs You should see something like this: @@ -77,9 +77,10 @@ RDoc::Task.new do |rdoc| rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" } rdoc_main.gsub!(%r{link:/rails/rails/blob/master/(\w+)/README\.rdoc}, "link:files/\\1/README_rdoc.html") - # Remove Travis build status image from API pages. Only GitHub README page gets this image - # https build image is used to avoid GitHub caching: http://about.travis-ci.org/docs/user/status-images - rdoc_main.gsub!(%r{^== Travis.*}, '') + # Remove Travis and Gemnasium status images from API pages. Only GitHub + # README page gets these images. Travis' https build image is used to avoid + # GitHub caching: http://about.travis-ci.org/docs/user/status-images + rdoc_main.gsub!(%r{^== (Build|Dependency) Status.*}, '') File.open(RDOC_MAIN, 'w') do |f| f.write(rdoc_main) @@ -189,7 +190,7 @@ end # desc 'Publishes docs, run this AFTER a new stable tag has been pushed' task :publish_docs do - Net::HTTP.new('rails-hooks.hashref.com').start do |http| + Net::HTTP.new('api.rubyonrails.org', 8080).start do |http| request = Net::HTTP::Post.new('/rails-master-hook') response = http.request(request) puts response.body diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 444754d0e9..5c03a29f0f 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -19,8 +19,9 @@ module ActionMailer options.stylesheets_dir ||= paths["public/stylesheets"].first # make sure readers methods get compiled - options.asset_path ||= app.config.asset_path - options.asset_host ||= app.config.asset_host + options.asset_path ||= app.config.asset_path + options.asset_host ||= app.config.asset_host + options.relative_url_root ||= app.config.relative_url_root ActiveSupport.on_load(:action_mailer) do include AbstractController::UrlFor diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 6d62d5eeec..b354f05960 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,43 @@ ## Rails 3.2.0 (unreleased) ## +* Add `button_tag` support to ActionView::Helpers::FormBuilder. + + This support mimics the default behavior of `submit_tag`. + + Example: + + <%= form_for @post do |f| %> + <%= f.button %> + <% end %> + +* Date helpers accept a new option, `:use_two_digit_numbers = true`, that renders select boxes for months and days with a leading zero without changing the respective values. + For example, this is useful for displaying ISO8601-style dates such as '2011-08-01'. *Lennart Fridén and Kim Persson* + +* Make ActiveSupport::Benchmarkable a default module for ActionController::Base, so the #benchmark method is once again available in the controller context like it used to be *DHH* + +* Deprecated implied layout lookup in controllers whose parent had a explicit layout set: + + class ApplicationController + layout "application" + end + + class PostsController < ApplicationController + end + + In the example above, Posts controller will no longer automatically look up for a posts layout. + + If you need this functionality you could either remove `layout "application"` from ApplicationController or explicitly set it to nil in PostsController. *José Valim* + +* Rails will now use your default layout (such as "layouts/application") when you specify a layout with `:only` and `:except` condition, and those conditions fail. *Prem Sichanugrist* + + For example, consider this snippet: + + class CarsController + layout 'single_car', :only => :show + end + + Rails will use 'layouts/single_car' when a request comes in `:show` action, and use 'layouts/application' (or 'layouts/cars', if exists) when a request comes in for any other actions. + * form_for with +:as+ option uses "#{action}_#{as}" as css class and id: Before: @@ -96,6 +134,11 @@ persistent between requests so if you need to manipulate the environment for your test you need to do it before the cookie jar is created. +* ActionController::ParamsWrapper on ActiveRecord models now only wrap + attr_accessible attributes if they were set, if not, only the attributes + returned by the class method attribute_names will be wrapped. This fixes + the wrapping of nested attributes by adding them to attr_accessible. + ## Rails 3.1.4 (unreleased) ## * Allow to use asset_path on named_routes aliasing RailsHelper's diff --git a/actionpack/examples/performance.rb b/actionpack/examples/performance.rb new file mode 100644 index 0000000000..994e745bb0 --- /dev/null +++ b/actionpack/examples/performance.rb @@ -0,0 +1,185 @@ +ENV['RAILS_ENV'] ||= 'production' + +require File.expand_path('../../../load_paths', __FILE__) +require 'action_pack' +require 'action_controller' +require 'action_view' +require 'active_model' +require 'benchmark' + +MyHash = Class.new(Hash) + +Hash.class_eval do + extend ActiveModel::Naming + include ActiveModel::Conversion +end + +class Runner + def initialize(app, output) + @app, @output = app, output + end + + def puts(*) + super if @output + end + + def call(env) + env['n'].to_i.times { @app.call(env) } + @app.call(env).tap { |response| report(env, response) } + end + + def report(env, response) + return unless ENV["DEBUG"] + out = env['rack.errors'] + out.puts response[0], response[1].to_yaml, '---' + response[2].each { |part| out.puts part } + out.puts '---' + end + + def self.puts(*) + super if @output + end + + def self.print(*) + super if @output + end + + def self.app_and_env_for(action, n) + env = Rack::MockRequest.env_for("/") + env.merge!('n' => n, 'rack.input' => StringIO.new(''), 'rack.errors' => $stdout) + app = lambda { |env| BasePostController.action(action).call(env) } + return app, env + end + + $ran = [] + + def self.run(action, n, output = true) + print "." + STDOUT.flush + @output = output + label = action.to_s + app, env = app_and_env_for(action, n) + t = Benchmark.realtime { new(app, output).call(env) } + $ran << [label, (t * 1000).to_i.to_s] if output + end + + def self.done + puts + header, content = "", "" + $ran.each do |k,v| + size = [k.size, v.size].max + 1 + header << format("%#{size}s", k) + content << format("%#{size}s", v) + end + puts header + puts content + end +end + +ActionController::Base.logger = nil +ActionController::Base.config.compile_methods! +ActionView::Resolver.caching = ENV["RAILS_ENV"] == "production" + +class BasePostController < ActionController::Base + append_view_path "#{File.dirname(__FILE__)}/views" + + def overhead + self.response_body = '' + end + + def index + render :text => '' + end + + $OBJECT = {:name => "Hello my name is omg", :address => "333 omg"} + + def partial + render :partial => "/collection", :object => $OBJECT + end + + def partial_10 + render :partial => "/ten_partials" + end + + def partial_100 + render :partial => "/hundred_partials" + end + + $COLLECTION1 = [] + 10.times do |i| + $COLLECTION1 << { :name => "Hello my name is omg", :address => "333 omg" } + end + + def coll_10 + render :partial => "/collection", :collection => $COLLECTION1 + end + + $COLLECTION2 = [] + 100.times do |i| + $COLLECTION2 << { :name => "Hello my name is omg", :address => "333 omg" } + end + + def coll_100 + render :partial => "/collection", :collection => $COLLECTION2 + end + + def uniq_100 + render :partial => $COLLECTION2 + end + + $COLLECTION3 = [] + 50.times do |i| + $COLLECTION3 << {:name => "Hello my name is omg", :address => "333 omg"} + $COLLECTION3 << MyHash.new(:name => "Hello my name is omg", :address => "333 omg") + end + + def diff_100 + render :partial => $COLLECTION3 + end + + def template_1 + render :template => "template" + end + + module Foo + def omg + "omg" + end + end + + helper Foo +end + +N = (ENV['N'] || 1000).to_i +# ActionController::Base.use_accept_header = false + +def run_all!(times, verbose) + Runner.run(:overhead, times, verbose) + Runner.run(:index, times, verbose) + Runner.run(:template_1, times, verbose) + Runner.run(:partial, times, verbose) + Runner.run(:partial_10, times, verbose) + Runner.run(:coll_10, times, verbose) + Runner.run(:partial_100, times, verbose) + Runner.run(:coll_100, times, verbose) + Runner.run(:uniq_100, times, verbose) + Runner.run(:diff_100, times, verbose) +end + +unless ENV["PROFILE"] + run_all!(1, false) + + (ENV["M"] || 1).to_i.times do + $ran = [] + run_all!(N, true) + Runner.done + end +else + Runner.run(ENV["PROFILE"].to_sym, 1, false) + require "ruby-prof" + RubyProf.start + Runner.run(ENV["PROFILE"].to_sym, N, true) + result = RubyProf.stop + printer = RubyProf::CallStackPrinter.new(result) + printer.print(File.open("output.html", "w")) +end
\ No newline at end of file diff --git a/actionpack/examples/views/_collection.erb b/actionpack/examples/views/_collection.erb new file mode 100644 index 0000000000..cee3fe64c0 --- /dev/null +++ b/actionpack/examples/views/_collection.erb @@ -0,0 +1,3 @@ +<%= collection[:name] %> +<%= collection[:address] %> +<%= omg %>
\ No newline at end of file diff --git a/actionpack/examples/views/_hello.erb b/actionpack/examples/views/_hello.erb new file mode 100644 index 0000000000..5ab2f8a432 --- /dev/null +++ b/actionpack/examples/views/_hello.erb @@ -0,0 +1 @@ +Hello
\ No newline at end of file diff --git a/actionpack/examples/views/_hundred_partials.erb b/actionpack/examples/views/_hundred_partials.erb new file mode 100644 index 0000000000..35c2a6c9d3 --- /dev/null +++ b/actionpack/examples/views/_hundred_partials.erb @@ -0,0 +1,3 @@ +<% 100.times do %> + <%= render :partial => "/collection", :object => $OBJECT %> +<% end %>
\ No newline at end of file diff --git a/actionpack/examples/views/_partial.erb b/actionpack/examples/views/_partial.erb new file mode 100644 index 0000000000..3ca8e80b52 --- /dev/null +++ b/actionpack/examples/views/_partial.erb @@ -0,0 +1,10 @@ +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> +<%= "Hello" %> diff --git a/actionpack/examples/views/_ten_partials.erb b/actionpack/examples/views/_ten_partials.erb new file mode 100644 index 0000000000..fd02991e22 --- /dev/null +++ b/actionpack/examples/views/_ten_partials.erb @@ -0,0 +1,10 @@ +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %> +<%= render :partial => '/collection', :object => $OBJECT %>
\ No newline at end of file diff --git a/actionpack/examples/views/hashes/_hash.erb b/actionpack/examples/views/hashes/_hash.erb new file mode 100644 index 0000000000..c100a290bd --- /dev/null +++ b/actionpack/examples/views/hashes/_hash.erb @@ -0,0 +1,3 @@ +<%= hash[:name] %> +<%= hash[:address] %> +<%= omg %>
\ No newline at end of file diff --git a/actionpack/examples/views/my_hashes/_my_hash.erb b/actionpack/examples/views/my_hashes/_my_hash.erb new file mode 100644 index 0000000000..e25d84101a --- /dev/null +++ b/actionpack/examples/views/my_hashes/_my_hash.erb @@ -0,0 +1,3 @@ +<%= my_hash[:name] %> +<%= my_hash[:address] %> +<%= omg %>
\ No newline at end of file diff --git a/actionpack/examples/views/template.html.erb b/actionpack/examples/views/template.html.erb new file mode 100644 index 0000000000..5ab2f8a432 --- /dev/null +++ b/actionpack/examples/views/template.html.erb @@ -0,0 +1 @@ +Hello
\ No newline at end of file diff --git a/actionpack/lib/abstract_controller/asset_paths.rb b/actionpack/lib/abstract_controller/asset_paths.rb index c2a6809f58..dd5f9a1942 100644 --- a/actionpack/lib/abstract_controller/asset_paths.rb +++ b/actionpack/lib/abstract_controller/asset_paths.rb @@ -4,7 +4,7 @@ module AbstractController included do config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, - :stylesheets_dir, :default_asset_host_protocol + :stylesheets_dir, :default_asset_host_protocol, :relative_url_root end end end diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index bbf5efe565..8b6136d6ba 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -66,27 +66,40 @@ module AbstractController # == Inheritance Examples # # class BankController < ActionController::Base - # layout "bank_standard" + # # bank.html.erb exists + # + # class ExchangeController < BankController + # # exchange.html.erb exists + # + # class CurrencyController < BankController # # class InformationController < BankController + # layout "information" # - # class TellerController < BankController + # class TellerController < InformationController # # teller.html.erb exists # - # class TillController < TellerController + # class EmployeeController < InformationController + # # employee.html.erb exists + # layout nil # # class VaultController < BankController # layout :access_level_layout # - # class EmployeeController < BankController - # layout nil + # class TillController < BankController + # layout false + # + # In these examples, we have three implicit lookup scenrios: + # * The BankController uses the "bank" layout. + # * The ExchangeController uses the "exchange" layout. + # * The CurrencyController inherits the layout from BankController. # - # In these examples: - # * The InformationController uses the "bank_standard" layout, inherited from BankController. - # * The TellerController follows convention and uses +app/views/layouts/teller.html.erb+. - # * The TillController inherits the layout from TellerController and uses +teller.html.erb+ as well. + # However, when a layout is explicitly set, the explicitly set layout wins: + # * The InformationController uses the "information" layout, explicitly set. + # * The TellerController also uses the "information" layout, because the parent explicitly set it. + # * The EmployeeController uses the "employee" layout, because it set the layout to nil, resetting the parent configuration. # * The VaultController chooses a layout dynamically by calling the <tt>access_level_layout</tt> method. - # * The EmployeeController does not use a layout at all. + # * The TillController does not use a layout at all. # # == Types of layouts # @@ -126,6 +139,22 @@ module AbstractController # If no directory is specified for the template name, the template will by default be looked for in <tt>app/views/layouts/</tt>. # Otherwise, it will be looked up relative to the template root. # + # Setting the layout to nil forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists. + # Setting it to nil is useful to re-enable template lookup overriding a previous configuration set in the parent: + # + # class ApplicationController < ActionController::Base + # layout "application" + # end + # + # class PostsController < ApplicationController + # # Will use "application" layout + # end + # + # class CommentsController < ApplicationController + # # Will search for "comments" layout and fallback "application" layout + # layout nil + # end + # # == Conditional layouts # # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering @@ -168,11 +197,12 @@ module AbstractController included do class_attribute :_layout_conditions remove_possible_method :_layout_conditions - delegate :_layout_conditions, :to => :'self.class' self._layout_conditions = {} _write_layout_method end + delegate :_layout_conditions, :to => "self.class" + module ClassMethods def inherited(klass) super @@ -188,7 +218,7 @@ module AbstractController # # ==== Returns # * <tt> Boolean</tt> - True if the action has a layout, false otherwise. - def action_has_layout? + def conditional_layout? return unless super conditions = _layout_conditions @@ -244,43 +274,71 @@ module AbstractController def _write_layout_method remove_possible_method(:_layout) - case defined?(@_layout) ? @_layout : nil - when String - self.class_eval %{def _layout; #{@_layout.inspect} end}, __FILE__, __LINE__ - when Symbol - self.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1 - def _layout - #{@_layout}.tap do |layout| - unless layout.is_a?(String) || !layout - raise ArgumentError, "Your layout method :#{@_layout} returned \#{layout}. It " \ - "should have returned a String, false, or nil" + prefixes = _implied_layout_name =~ /\blayouts/ ? [] : ["layouts"] + name_clause = if name + <<-RUBY + lookup_context.find_all("#{_implied_layout_name}", #{prefixes.inspect}).first || super + RUBY + end + + if defined?(@_layout) + layout_definition = case @_layout + when String + @_layout.inspect + when Symbol + <<-RUBY + #{@_layout}.tap do |layout| + unless layout.is_a?(String) || !layout + raise ArgumentError, "Your layout method :#{@_layout} returned \#{layout}. It " \ + "should have returned a String, false, or nil" + end end - end + RUBY + when Proc + define_method :_layout_from_proc, &@_layout + "_layout_from_proc(self)" + when false + nil + when true + raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil" + when nil + name_clause end - ruby_eval - when Proc - define_method :_layout_from_proc, &@_layout - self.class_eval %{def _layout; _layout_from_proc(self) end}, __FILE__, __LINE__ - when false - self.class_eval %{def _layout; end}, __FILE__, __LINE__ - when true - raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil" - when nil - if name - _prefixes = _implied_layout_name =~ /\blayouts/ ? [] : ["layouts"] + else + # Add a deprecation if the parent layout was explicitly set and the child + # still does a dynamic lookup. In next Rails release, we should @_layout + # to be inheritable so we can skip the child lookup if the parent explicitly + # set the layout. + parent = self.superclass.instance_variable_get(:@_layout) + @_layout = nil + inspect = parent.is_a?(Proc) ? parent.inspect : parent - self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def _layout - if template_exists?("#{_implied_layout_name}", #{_prefixes.inspect}) - "#{_implied_layout_name}" + layout_definition = if parent.nil? + name_clause + elsif name + <<-RUBY + if template = lookup_context.find_all("#{_implied_layout_name}", #{prefixes.inspect}).first + ActiveSupport::Deprecation.warn 'Layout found at "#{_implied_layout_name}" for #{name} but parent controller ' \ + 'set layout to #{inspect.inspect}. Please explicitly set your layout to "#{_implied_layout_name}" ' \ + 'or set it to nil to force a dynamic lookup.' + template else super end - end - RUBY - end + RUBY + end end - self.class_eval { private :_layout } + + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def _layout + if conditional_layout? + #{layout_definition} + else + #{name_clause} + end + end + private :_layout + RUBY end end @@ -289,8 +347,7 @@ module AbstractController if _include_layout?(options) layout = options.key?(:layout) ? options.delete(:layout) : :default - value = _layout_for_option(layout) - options[:layout] = (value =~ /\blayouts/ ? value : "layouts/#{value}") if value + options[:layout] = _layout_for_option(layout) end end @@ -305,6 +362,10 @@ module AbstractController @_action_has_layout end + def conditional_layout? + true + end + private # This will be overwritten by _write_layout_method @@ -316,9 +377,10 @@ module AbstractController # * <tt>name</tt> - The name of the template def _layout_for_option(name) case name - when String then name - when true then _default_layout(true) - when :default then _default_layout(false) + when String then _normalize_layout(name) + when Proc then name + when true then Proc.new { _default_layout(true) } + when :default then Proc.new { _default_layout(false) } when false, nil then nil else raise ArgumentError, @@ -326,6 +388,10 @@ module AbstractController end end + def _normalize_layout(value) + value.is_a?(String) && value !~ /\blayouts/ ? "layouts/#{value}" : value + end + # Returns the default layout for this controller. # Optionally raises an exception if the layout could not be found. # @@ -337,17 +403,17 @@ module AbstractController # * <tt>template</tt> - The template object for the default layout (or nil) def _default_layout(require_layout = false) begin - layout_name = _layout if action_has_layout? + value = _layout if action_has_layout? rescue NameError => e raise e, "Could not render layout: #{e.message}" end - if require_layout && action_has_layout? && !layout_name + if require_layout && action_has_layout? && !value raise ArgumentError, "There was no default layout for #{self.class} in #{view_paths.inspect}" end - layout_name + _normalize_layout(value) end def _include_layout?(options) diff --git a/actionpack/lib/abstract_controller/logger.rb b/actionpack/lib/abstract_controller/logger.rb index 0b196119f4..8b36230397 100644 --- a/actionpack/lib/abstract_controller/logger.rb +++ b/actionpack/lib/abstract_controller/logger.rb @@ -7,7 +7,7 @@ module AbstractController included do config_accessor :logger - extend ActiveSupport::Benchmarkable + include ActiveSupport::Benchmarkable end end end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 41fdc11196..d95770c049 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -66,12 +66,7 @@ module AbstractController end def view_context_class - @_view_context_class || self.class.view_context_class - end - - def initialize(*) - @_view_context_class = nil - super + @_view_context_class ||= self.class.view_context_class end # An instance of a view class. The default view class is ActionView::Base diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb index e8394447a7..96118b940f 100644 --- a/actionpack/lib/abstract_controller/view_paths.rb +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -10,7 +10,7 @@ module AbstractController self._view_paths.freeze end - delegate :find_template, :template_exists?, :view_paths, :formats, :formats=, + delegate :template_exists?, :view_paths, :formats, :formats=, :locale, :locale=, :to => :lookup_context module ClassMethods diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index de250053d3..4c76f4c43b 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -24,7 +24,6 @@ module ActionController end message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration message << " (#{additions.join(" | ")})" unless additions.blank? - message << "\n" info(message) end diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index 9dcea86253..5c28a8074f 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -43,6 +43,11 @@ module ActionController # wrap_parameters :person, :include => [:username, :password] # end # + # On ActiveRecord models with no +:include+ or +:exclude+ option set, + # if attr_accessible is set on that model, it will only wrap the accessible + # parameters, else it will only wrap the parameters returned by the class + # method attribute_names. + # # If you're going to pass the parameters to an +ActiveModel+ object (such as # +User.new(params[:user])+), you might consider passing the model class to # the method instead. The +ParamsWrapper+ will actually try to determine the @@ -162,7 +167,9 @@ module ActionController unless options[:include] || options[:exclude] model ||= _default_wrap_model - if model.respond_to?(:attribute_names) && model.attribute_names.present? + if model.respond_to?(:accessible_attributes) && model.accessible_attributes.present? + options[:include] = model.accessible_attributes.to_a + elsif model.respond_to?(:attribute_names) && model.attribute_names.present? options[:include] = model.attribute_names end end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index de7b837ecc..cb2e2b17aa 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -31,6 +31,7 @@ module ActionController # make sure readers methods get compiled options.asset_path ||= app.config.asset_path options.asset_host ||= app.config.asset_host + options.relative_url_root ||= app.config.relative_url_root ActiveSupport.on_load(:action_controller) do include app.routes.mounted_helpers diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 6913c1ef4a..1731388bf3 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -86,6 +86,21 @@ module ActionController end end when Hash + if expected_layout = options[:layout] + msg = build_message(message, + "expecting layout <?> but action rendered <?>", + expected_layout, @layouts.keys) + + case expected_layout + when String + assert(@layouts.keys.include?(expected_layout), msg) + when Regexp + assert(@layouts.keys.any? {|l| l =~ expected_layout }, msg) + when nil + assert(@layouts.empty?, msg) + end + end + if expected_partial = options[:partial] if expected_locals = options[:locals] actual_locals = @locals[expected_partial.to_s.sub(/^_/,'')] @@ -98,19 +113,6 @@ module ActionController "expecting ? to be rendered ? time(s) but rendered ? time(s)", expected_partial, expected_count, actual_count) assert(actual_count == expected_count.to_i, msg) - elsif options.key?(:layout) - msg = build_message(message, - "expecting layout <?> but action rendered <?>", - expected_layout, @layouts.keys) - - case layout = options[:layout] - when String - assert(@layouts.include?(expected_layout), msg) - when Regexp - assert(@layouts.any? {|l| l =~ layout }, msg) - when nil - assert(@layouts.empty?, msg) - end else msg = build_message(message, "expecting partial <?> but action rendered <?>", diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index aaed0d750f..bea62b94d2 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -4,14 +4,18 @@ module ActionDispatch module Http module Cache module Request + + HTTP_IF_MODIFIED_SINCE = 'HTTP_IF_MODIFIED_SINCE'.freeze + HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze + def if_modified_since - if since = env['HTTP_IF_MODIFIED_SINCE'] + if since = env[HTTP_IF_MODIFIED_SINCE] Time.rfc2822(since) rescue nil end end def if_none_match - env['HTTP_IF_NONE_MATCH'] + env[HTTP_IF_NONE_MATCH] end def not_modified?(modified_at) @@ -43,31 +47,35 @@ module ActionDispatch alias :etag? :etag def last_modified - if last = headers['Last-Modified'] + if last = headers[LAST_MODIFIED] Time.httpdate(last) end end def last_modified? - headers.include?('Last-Modified') + headers.include?(LAST_MODIFIED) end def last_modified=(utc_time) - headers['Last-Modified'] = utc_time.httpdate + headers[LAST_MODIFIED] = utc_time.httpdate end def etag=(etag) key = ActiveSupport::Cache.expand_cache_key(etag) - @etag = self["ETag"] = %("#{Digest::MD5.hexdigest(key)}") + @etag = self[ETAG] = %("#{Digest::MD5.hexdigest(key)}") end private + LAST_MODIFIED = "Last-Modified".freeze + ETAG = "ETag".freeze + CACHE_CONTROL = "Cache-Control".freeze + def prepare_cache_control! @cache_control = {} - @etag = self["ETag"] + @etag = self[ETAG] - if cache_control = self["Cache-Control"] + if cache_control = self[CACHE_CONTROL] cache_control.split(/,\s*/).each do |segment| first, last = segment.split("=") @cache_control[first.to_sym] = last || true @@ -81,28 +89,32 @@ module ActionDispatch end end - DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate" + DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze + NO_CACHE = "no-cache".freeze + PUBLIC = "public".freeze + PRIVATE = "private".freeze + MUST_REVALIDATE = "must-revalidate".freeze def set_conditional_cache_control! - return if self["Cache-Control"].present? + return if self[CACHE_CONTROL].present? control = @cache_control if control.empty? - headers["Cache-Control"] = DEFAULT_CACHE_CONTROL + headers[CACHE_CONTROL] = DEFAULT_CACHE_CONTROL elsif control[:no_cache] - headers["Cache-Control"] = "no-cache" + headers[CACHE_CONTROL] = NO_CACHE else extras = control[:extras] max_age = control[:max_age] options = [] options << "max-age=#{max_age.to_i}" if max_age - options << (control[:public] ? "public" : "private") - options << "must-revalidate" if control[:must_revalidate] + options << (control[:public] ? PUBLIC : PRIVATE) + options << MUST_REVALIDATE if control[:must_revalidate] options.concat(extras) if extras - headers["Cache-Control"] = options.join(", ") + headers[CACHE_CONTROL] = options.join(", ") end end end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb index 1480e8f77c..490b46c990 100644 --- a/actionpack/lib/action_dispatch/http/parameter_filter.rb +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -20,6 +20,8 @@ module ActionDispatch @filters.present? end + FILTERED = '[FILTERED]'.freeze + def compiled_filter @compiled_filter ||= begin regexps, blocks = compile_filter @@ -29,7 +31,7 @@ module ActionDispatch original_params.each do |key, value| if regexps.find { |r| key =~ r } - value = '[FILTERED]' + value = FILTERED elsif value.is_a?(Hash) value = filter(value) elsif value.is_a?(Array) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index e86dfd64d2..c5c48ec489 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -35,14 +35,6 @@ module ActionDispatch METHOD end - def self.new(env) - if request = env["action_dispatch.request"] && request.instance_of?(self) - return request - end - - super - end - def key?(key) @env.key?(key) end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index f1e85559a3..5797c63924 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -53,8 +53,10 @@ module ActionDispatch # :nodoc: # information. attr_accessor :charset, :content_type - CONTENT_TYPE = "Content-Type" - + CONTENT_TYPE = "Content-Type".freeze + SET_COOKIE = "Set-Cookie".freeze + LOCATION = "Location".freeze + cattr_accessor(:default_charset) { "utf-8" } include Rack::Response::Helpers @@ -66,10 +68,10 @@ module ActionDispatch # :nodoc: @sending_file = false @blank = false - if content_type = self["Content-Type"] + if content_type = self[CONTENT_TYPE] type, charset = content_type.split(/;\s*charset=/) @content_type = Mime::Type.lookup(type) - @charset = charset || "UTF-8" + @charset = charset || self.class.default_charset end prepare_cache_control! @@ -109,9 +111,9 @@ module ActionDispatch # :nodoc: end def body - str = '' - each { |part| str << part.to_s } - str + strings = [] + each { |part| strings << part.to_s } + strings.join end EMPTY = " " @@ -142,12 +144,12 @@ module ActionDispatch # :nodoc: end def location - headers['Location'] + headers[LOCATION] end alias_method :redirect_url, :location def location=(url) - headers['Location'] = url + headers[LOCATION] = url end def close @@ -158,10 +160,10 @@ module ActionDispatch # :nodoc: assign_default_content_type_and_charset! handle_conditional_get! - @header["Set-Cookie"] = @header["Set-Cookie"].join("\n") if @header["Set-Cookie"].respond_to?(:join) + @header[SET_COOKIE] = @header[SET_COOKIE].join("\n") if @header[SET_COOKIE].respond_to?(:join) if [204, 304].include?(@status) - @header.delete "Content-Type" + @header.delete CONTENT_TYPE [@status, @header, []] else [@status, @header, self] @@ -175,7 +177,7 @@ module ActionDispatch # :nodoc: # assert_equal 'AuthorOfNewPage', r.cookies['author'] def cookies cookies = {} - if header = self["Set-Cookie"] + if header = self[SET_COOKIE] header = header.split("\n") if header.respond_to?(:to_str) header.each do |cookie| if pair = cookie.split(';').first diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index 417701ea54..cd4af82c6e 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -59,10 +59,13 @@ module ActionDispatch exception = wrapper.exception + trace = wrapper.application_trace + trace = wrapper.framework_trace if trace.empty? + ActiveSupport::Deprecation.silence do message = "\n#{exception.class} (#{exception.message}):\n" message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code) - message << " " << wrapper.application_trace.join("\n ") + message << " " << trace.join("\n ") logger.fatal("#{message}\n\n") end end diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb index 29289a76b4..4f48f1c974 100644 --- a/actionpack/lib/action_dispatch/middleware/reloader.rb +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -43,34 +43,58 @@ module ActionDispatch # Execute all prepare callbacks. def self.prepare! - new(nil).run_callbacks :prepare + new(nil).prepare! end # Execute all cleanup callbacks. def self.cleanup! - new(nil).run_callbacks :cleanup + new(nil).cleanup! end - def initialize(app) + def initialize(app, condition=nil) @app = app - end - - module CleanupOnClose - def close - super if defined?(super) - ensure - ActionDispatch::Reloader.cleanup! - end + @condition = condition || lambda { true } + @validated = true end def call(env) - run_callbacks :prepare + @validated = @condition.call + prepare! response = @app.call(env) - response[2].extend(CleanupOnClose) + response[2].extend(module_hook) response rescue Exception - run_callbacks :cleanup + cleanup! raise end + + def prepare! #:nodoc: + run_callbacks :prepare if validated? + end + + def cleanup! #:nodoc: + run_callbacks :cleanup if validated? + ensure + @validated = true + end + + private + + def validated? #:nodoc: + @validated + end + + def module_hook #:nodoc: + middleware = self + Module.new do + define_method :close do + begin + super() if defined?(super) + ensure + middleware.cleanup! + end + end + end + end end end diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 2ba3198ebd..a4f4825f92 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -21,6 +21,7 @@ module ActionDispatch initializer "action_dispatch.configure" do |app| ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header + ActionDispatch::Response.default_charset = app.config.encoding ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses) ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates) diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index e989a38d8b..013cf93dbc 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -165,7 +165,7 @@ module ActionDispatch if parent.is_a?(Symbol) || parent.is_a?(String) parent else - ActiveModel::Naming.route_key(parent).singularize + ActiveModel::Naming.singular_route_key(parent) end end else @@ -176,9 +176,11 @@ module ActionDispatch if record.is_a?(Symbol) || record.is_a?(String) route << record elsif record - route << ActiveModel::Naming.route_key(record) - route = [route.join("_").singularize] if inflection == :singular - route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural + if inflection == :singular + route << ActiveModel::Naming.singular_route_key(record) + else + route << ActiveModel::Naming.route_key(record) + end else raise ArgumentError, "Nil location provided. Can't build URI." end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index c64214431a..6d6de36a08 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -557,7 +557,7 @@ module ActionDispatch path_addition, params = generate(path_options, path_segments || {}) path << path_addition - ActionDispatch::Http::URL.url_for(options.merge({ + ActionDispatch::Http::URL.url_for(options.merge!({ :path => path, :params => params, :user => user, diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 39ba83fb9a..22e41c9c16 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -145,7 +145,7 @@ module ActionDispatch when String options when nil, Hash - _routes.url_for((options || {}).reverse_merge(url_options).symbolize_keys) + _routes.url_for((options || {}).symbolize_keys.reverse_merge!(url_options)) else polymorphic_url(options) end diff --git a/actionpack/lib/action_view/data/encoding_conversions.txt b/actionpack/lib/action_view/data/encoding_conversions.txt deleted file mode 100644 index fdfbe28803..0000000000 --- a/actionpack/lib/action_view/data/encoding_conversions.txt +++ /dev/null @@ -1,88 +0,0 @@ -ASCII-8BIT:UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-8:ASCII-8BIT,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -US-ASCII:ASCII-8BIT,UTF-8,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Big5:ASCII-8BIT,UTF-8,US-ASCII,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Big5-HKSCS:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Big5-UAO:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP949:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -EUC-JP:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -EUC-KR:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -GB18030:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -GBK:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-1:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-2:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-3:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-4:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-5:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-6:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-7:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-8:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-9:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-10:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-11:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-13:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-14:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-8859-15:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -KOI8-R:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -KOI8-U:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Shift_JIS:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-16BE:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-16LE:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-32BE:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-32LE:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1251:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM437:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM737:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM775:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP850:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM852:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP852:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM855:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP855:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM857:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM860:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM861:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM862:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM863:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM865:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM866:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -IBM869:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macCroatian:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macCyrillic:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macGreek:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macIceland:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macRoman:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macRomania:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macTurkish:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -macUkraine:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP950:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP951:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -stateless-ISO-2022-JP:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -eucJP-ms:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP51932:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -GB2312:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -GB12345:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-2022-JP:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP50220:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -CP50221:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1252:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1250:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1256:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1253:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1255:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1254:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -TIS-620:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-874:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-1257:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -Windows-31J:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF8-MAC:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-16:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF-32:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF8-DoCoMo:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -SJIS-DoCoMo:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF8-KDDI:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -SJIS-KDDI:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -ISO-2022-JP-KDDI:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -stateless-ISO-2022-JP-KDDI:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,UTF8-SoftBank,SJIS-SoftBank -UTF8-SoftBank:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,SJIS-SoftBank -SJIS-SoftBank:ASCII-8BIT,UTF-8,US-ASCII,Big5,Big5-HKSCS,Big5-UAO,CP949,EUC-JP,EUC-KR,GB18030,GBK,ISO-8859-1,ISO-8859-2,ISO-8859-3,ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,ISO-8859-9,ISO-8859-10,ISO-8859-11,ISO-8859-13,ISO-8859-14,ISO-8859-15,KOI8-R,KOI8-U,Shift_JIS,UTF-16BE,UTF-16LE,UTF-32BE,UTF-32LE,Windows-1251,IBM437,IBM737,IBM775,CP850,IBM852,CP852,IBM855,CP855,IBM857,IBM860,IBM861,IBM862,IBM863,IBM865,IBM866,IBM869,macCroatian,macCyrillic,macGreek,macIceland,macRoman,macRomania,macTurkish,macUkraine,CP950,CP951,stateless-ISO-2022-JP,eucJP-ms,CP51932,GB2312,GB12345,ISO-2022-JP,CP50220,CP50221,Windows-1252,Windows-1250,Windows-1256,Windows-1253,Windows-1255,Windows-1254,TIS-620,Windows-874,Windows-1257,Windows-31J,UTF8-MAC,UTF-16,UTF-32,UTF8-DoCoMo,SJIS-DoCoMo,UTF8-KDDI,SJIS-KDDI,ISO-2022-JP-KDDI,stateless-ISO-2022-JP-KDDI,UTF8-SoftBank
\ No newline at end of file diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 4deb87180c..38cf922ef4 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -736,7 +736,7 @@ module ActionView if @options[:use_hidden] || @options[:discard_day] build_hidden(:day, day) else - build_options_and_select(:day, day, :start => 1, :end => 31, :leading_zeros => false) + build_options_and_select(:day, day, :start => 1, :end => 31, :leading_zeros => false, :use_two_digit_numbers => @options[:use_two_digit_numbers]) end end @@ -822,6 +822,8 @@ module ActionView def month_name(number) if @options[:use_month_numbers] number + elsif @options[:use_two_digit_numbers] + sprintf "%02d", number elsif @options[:add_month_numbers] "#{number} - #{month_names[number]}" else @@ -857,7 +859,7 @@ module ActionView start = options.delete(:start) || 0 stop = options.delete(:end) || 59 step = options.delete(:step) || 1 - options.reverse_merge!({:leading_zeros => true, :ampm => false}) + options.reverse_merge!({:leading_zeros => true, :ampm => false, :use_two_digit_numbers => false}) leading_zeros = options.delete(:leading_zeros) select_options = [] @@ -865,7 +867,8 @@ module ActionView value = leading_zeros ? sprintf("%02d", i) : i tag_options = { :value => value } tag_options[:selected] = "selected" if selected == i - text = options[:ampm] ? AMPM_TRANSLATION[i] : value + text = options[:use_two_digit_numbers] ? sprintf("%02d", i) : value + text = options[:ampm] ? AMPM_TRANSLATION[i] : text select_options << content_tag(:option, text, tag_options) end (select_options.join("\n") + "\n").html_safe diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 1a64b12aa6..ccb2275329 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1364,6 +1364,39 @@ module ActionView @template.submit_tag(value, options) end + # Add the submit button for the given form. When no value is given, it checks + # if the object is a new resource or not to create the proper label: + # + # <%= form_for @post do |f| %> + # <%= f.button %> + # <% end %> + # + # In the example above, if @post is a new record, it will use "Create Post" as + # submit button label, otherwise, it uses "Update Post". + # + # Those labels can be customized using I18n, under the helpers.submit key and accept + # the %{model} as translation interpolation: + # + # en: + # helpers: + # button: + # create: "Create a %{model}" + # update: "Confirm changes to %{model}" + # + # It also searches for a key specific for the given object: + # + # en: + # helpers: + # button: + # post: + # create: "Add %{model}" + # + def button(value=nil, options={}) + value, options = nil, value if value.is_a?(Hash) + value ||= submit_default_value + @template.button_tag(value, options) + end + def emitted_hidden_id? @emitted_hidden_id ||= nil end diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index bcc8f6fbcb..7768c8c151 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/object/try' require 'action_controller/vendor/html-scanner' -require 'action_view/helpers/tag_helper' module ActionView # = Action View Sanitize Helpers diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index bc8572fe69..209360ee82 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/filters' -require 'action_view/helpers/tag_helper' module ActionView # = Action View Text Helpers @@ -31,6 +30,7 @@ module ActionView extend ActiveSupport::Concern include SanitizeHelper + include TagHelper # The preferred method of outputting text in your views is to use the # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods # do not operate as expected in an eRuby code block. If you absolutely must diff --git a/actionpack/lib/action_view/locale/en.yml b/actionpack/lib/action_view/locale/en.yml index eb816b9446..f2a83b92a9 100644 --- a/actionpack/lib/action_view/locale/en.yml +++ b/actionpack/lib/action_view/locale/en.yml @@ -152,3 +152,9 @@ update: 'Update %{model}' submit: 'Save %{model}' + # Default translation keys for button FormHelper + button: + create: 'Create %{model}' + update: 'Update %{model}' + submit: 'Save %{model}' + diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index fa4bf70f77..95478b9af6 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -20,7 +20,7 @@ module ActionView def self.register_detail(name, options = {}, &block) self.registered_details << name - initialize = registered_details.map { |n| "self.#{n} = details[:#{n}]" } + initialize = registered_details.map { |n| "@details[:#{n}] = details[:#{n}] || default_#{n}" } Accessors.send :define_method, :"default_#{name}", &block Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1 @@ -29,7 +29,7 @@ module ActionView end def #{name}=(value) - value = Array.wrap(value.presence || default_#{name}) + value = value.present? ? Array.wrap(value) : default_#{name} _set_detail(:#{name}, value) if value != @details[:#{name}] end @@ -44,7 +44,7 @@ module ActionView module Accessors #:nodoc: end - register_detail(:locale) { [I18n.locale, I18n.default_locale] } + register_detail(:locale) { [I18n.locale, I18n.default_locale].uniq } register_detail(:formats) { Mime::SET.symbols } register_detail(:handlers){ Template::Handlers.extensions } @@ -56,7 +56,7 @@ module ActionView @details_keys = Hash.new def self.get(details) - @details_keys[details.freeze] ||= new + @details_keys[details] ||= new end def initialize @@ -86,8 +86,7 @@ module ActionView def _set_detail(key, value) @details_key = nil - @details = @details.dup if @details.frozen? - @details[key] = value.freeze + @details[key] = value end end @@ -153,14 +152,14 @@ module ActionView "" end - parts = name.split('/') - name = parts.pop + prefixes = nil if prefixes.blank? + parts = name.split('/') + name = parts.pop - prefixes = if prefixes.blank? - [parts.join('/')] - else - prefixes.map { |prefix| [prefix, *parts].compact.join('/') } - end + return name, prefixes || [""] if parts.empty? + + parts = parts.join('/') + prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts] return name, prefixes end @@ -227,7 +226,6 @@ module ActionView end # A method which only uses the first format in the formats array for layout lookup. - # This method plays straight with instance variables for performance reasons. def with_layout_format if formats.size == 1 yield diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index 54a0ba96ff..374bdb62f5 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -82,16 +82,18 @@ module ActionView # # This will render the partial "advertisement/_ad.html.erb" regardless of which controller this is being called from. # - # == Rendering objects with the RecordIdentifier + # == Rendering objects that respond to `to_partial_path` # - # Instead of explicitly naming the location of a partial, you can also let the RecordIdentifier do the work if - # you're following its conventions for RecordIdentifier#partial_path. Examples: + # Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work + # and pick the proper path by checking `to_proper_path` method. If the object passed to render is a collection, + # all objects must return the same path. # - # # @account is an Account instance, so it uses the RecordIdentifier to replace + # # @account.to_partial_path returns 'accounts/account', so it can be used to replace: # # <%= render :partial => "accounts/account", :locals => { :account => @account} %> # <%= render :partial => @account %> # - # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # # @posts is an array of Post instances, so every post record returns 'posts/post' on `to_partial_path`, + # # that's why we can replace: # # <%= render :partial => "posts/post", :collection => @posts %> # <%= render :partial => @posts %> # @@ -106,13 +108,14 @@ module ActionView # # Instead of <%= render :partial => "account", :locals => { :account => @buyer } %> # <%= render "account", :account => @buyer %> # - # # @account is an Account instance, so it uses the RecordIdentifier to replace - # # <%= render :partial => "accounts/account", :locals => { :account => @account } %> - # <%= render(@account) %> + # # @account.to_partial_path returns 'accounts/account', so it can be used to replace: + # # <%= render :partial => "accounts/account", :locals => { :account => @account} %> + # <%= render @account %> # - # # @posts is an array of Post instances, so it uses the RecordIdentifier to replace + # # @posts is an array of Post instances, so every post record returns 'posts/post' on `to_partial_path`, + # # that's why we can replace: # # <%= render :partial => "posts/post", :collection => @posts %> - # <%= render(@posts) %> + # <%= render @posts %> # # == Rendering partials with layouts # @@ -205,7 +208,7 @@ module ActionView # Deadline: <%= user.deadline %> # <%- end -%> # <% end %> - class PartialRenderer < AbstractRenderer #:nodoc: + class PartialRenderer < AbstractRenderer PARTIAL_NAMES = Hash.new { |h,k| h[k] = {} } def initialize(*) @@ -375,23 +378,23 @@ module ActionView end end - @partial_names[path] ||= path.dup.tap do |object_path| - merge_prefix_into_object_path(@context_prefix, object_path) - end + @partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup) end def merge_prefix_into_object_path(prefix, object_path) if prefix.include?(?/) && object_path.include?(?/) - overlap = [] + prefixes = [] prefix_array = File.dirname(prefix).split('/') object_path_array = object_path.split('/')[0..-3] # skip model dir & partial prefix_array.each_with_index do |dir, index| - overlap << dir if dir == object_path_array[index] + break if dir == object_path_array[index] + prefixes << dir end - object_path.gsub!(/^#{overlap.join('/')}\//,'') - object_path.insert(0, "#{File.dirname(prefix)}/") + (prefixes << object_path).join("/") + else + object_path end end diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index ac91d333ba..e131afa279 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -58,14 +58,28 @@ module ActionView # context object. If no layout is found, it checks if at least a layout with # the given name exists across all details before raising the error. def find_layout(layout, keys) - begin - with_layout_format do - layout =~ /^\// ? - with_fallbacks { find_template(layout, nil, false, keys, @details) } : find_template(layout, nil, false, keys, @details) + with_layout_format { resolve_layout(layout, keys) } + end + + def resolve_layout(layout, keys) + case layout + when String + begin + if layout =~ /^\// + with_fallbacks { find_template(layout, nil, false, keys, @details) } + else + find_template(layout, nil, false, keys, @details) + end + rescue ActionView::MissingTemplate + all_details = @details.merge(:formats => @lookup_context.default_formats) + raise unless template_exists?(layout, nil, false, keys, all_details) end - rescue ActionView::MissingTemplate - all_details = @details.merge(:formats => @lookup_context.default_formats) - raise unless template_exists?(layout, nil, false, keys, all_details) + when Proc + resolve_layout(layout.call, keys) + when FalseClass + nil + else + layout end end end diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 8d69880308..10797c010f 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -3,33 +3,6 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/core_ext/kernel/singleton_class' -if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' && RUBY_VERSION == '1.9.3' && RUBY_PATCHLEVEL == 0 - # This is a hack to work around a bug in Ruby 1.9.3p0: - # http://redmine.ruby-lang.org/issues/5564 - # - # Basically, at runtime we may need to perform some encoding conversions on the templates, - # but if the converter hasn't been loaded by Ruby beforehand (i.e. now), then it won't be - # able to find it (due to a bug). - # - # However, we don't know what conversions we may need to do a runtime. So we load up a - # text file which contains a pre-generated list of all the possible conversions, - # and we load all of them. - # - # In my testing this increased the process size by about 3.9 MB (after the conversions array - # is GC'd) and took around 170ms to run, which seems acceptable for a workaround. - # - # The script to dump the conversions is: https://gist.github.com/1371499 - - filename = File.join(File.dirname(__FILE__), 'data', 'encoding_conversions.txt') - conversions = File.read(filename) - conversions.split("\n").map do |line| - from, to_array = line.split(':') - to_array.split(',').each do |to| - Encoding::Converter.new(from, to) - end - end -end - module ActionView # = Action View Template class Template diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 75ba1e66c2..1bd9d5ca26 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -26,7 +26,7 @@ module Sprockets sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'js') asset.to_a.map { |dep| - super(dep.to_s, { :src => path_to_asset(dep, :ext => 'js', :body => true, :digest => digest) }.merge!(options)) + super(dep.pathname.to_s, { :src => path_to_asset(dep, :ext => 'js', :body => true, :digest => digest) }.merge!(options)) } else super(source.to_s, { :src => path_to_asset(source, :ext => 'js', :body => body, :digest => digest) }.merge!(options)) @@ -43,7 +43,7 @@ module Sprockets sources.collect do |source| if debug && asset = asset_paths.asset_for(source, 'css') asset.to_a.map { |dep| - super(dep.to_s, { :href => path_to_asset(dep, :ext => 'css', :body => true, :protocol => :request, :digest => digest) }.merge!(options)) + super(dep.pathname.to_s, { :href => path_to_asset(dep, :ext => 'css', :body => true, :protocol => :request, :digest => digest) }.merge!(options)) } else super(source.to_s, { :href => path_to_asset(source, :ext => 'css', :body => body, :protocol => :request, :digest => digest) }.merge!(options)) @@ -57,7 +57,7 @@ module Sprockets options[:body] ? "#{path}?body=1" : path end alias_method :path_to_asset, :asset_path # aliased to avoid conflicts with an asset_path named route - + def image_path(source) path_to_asset(source) end diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 86208899f8..de6f42d826 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -141,6 +141,30 @@ module AbstractControllerTests end end + class WithOnlyConditional < WithStringImpliedChild + layout "overwrite", :only => :show + + def index + render :template => ActionView::Template::Text.new("Hello index!") + end + + def show + render :template => ActionView::Template::Text.new("Hello show!") + end + end + + class WithExceptConditional < WithStringImpliedChild + layout "overwrite", :except => :show + + def index + render :template => ActionView::Template::Text.new("Hello index!") + end + + def show + render :template => ActionView::Template::Text.new("Hello show!") + end + end + class TestBase < ActiveSupport::TestCase test "when no layout is specified, and no default is available, render without a layout" do controller = Blank.new @@ -234,7 +258,7 @@ module AbstractControllerTests test "when a child controller has an implied layout, use that layout and not the parent controller layout" do controller = WithStringImpliedChild.new - controller.process(:index) + assert_deprecated { controller.process(:index) } assert_equal "With Implied Hello string!", controller.response_body end @@ -247,7 +271,7 @@ module AbstractControllerTests test "when a grandchild has no layout specified, the child has an implied layout, and the " \ "parent has specified a layout, use the child controller layout" do controller = WithChildOfImplied.new - controller.process(:index) + assert_deprecated { controller.process(:index) } assert_equal "With Implied Hello string!", controller.response_body end @@ -260,6 +284,30 @@ module AbstractControllerTests end end end + + test "when specify an :only option which match current action name" do + controller = WithOnlyConditional.new + controller.process(:show) + assert_equal "Overwrite Hello show!", controller.response_body + end + + test "when specify an :only option which does not match current action name" do + controller = WithOnlyConditional.new + controller.process(:index) + assert_equal "With Implied Hello index!", controller.response_body + end + + test "when specify an :except option which match current action name" do + controller = WithExceptConditional.new + controller.process(:show) + assert_equal "With Implied Hello show!", controller.response_body + end + + test "when specify an :except option which does not match current action name" do + controller = WithExceptConditional.new + controller.process(:index) + assert_equal "Overwrite Hello index!", controller.response_body + end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index a714e8bbcc..b414327d08 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -71,6 +71,10 @@ class ActionPackAssertionsController < ActionController::Base render :text => "Hello!", :content_type => Mime::RSS end + def render_with_layout + render "test/hello_world", :layout => "layouts/standard" + end + def session_stuffing session['xmas'] = 'turkey' render :text => "ho ho ho" @@ -471,6 +475,18 @@ class AssertTemplateTest < ActionController::TestCase end end + def test_fails_with_wrong_layout + get :render_with_layout + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template :layout => "application" + end + end + + def test_passes_with_correct_layout + get :render_with_layout + assert_template :layout => "layouts/standard" + end + def test_assert_template_reset_between_requests get :hello_world assert_template 'test/hello_world' diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index 25299eb8b8..bc171e201b 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -167,7 +167,7 @@ class LayoutSetInResponseTest < ActionController::TestCase def test_layout_is_picked_from_the_controller_instances_view_path @controller = PrependsViewPathController.new get :hello - assert_template :layout => /layouts\/alt\.\w+/ + assert_template :layout => /layouts\/alt/ end def test_absolute_pathed_layout diff --git a/actionpack/test/controller/new_base/render_layout_test.rb b/actionpack/test/controller/new_base/render_layout_test.rb index d3dcb5cad6..4ac40ca405 100644 --- a/actionpack/test/controller/new_base/render_layout_test.rb +++ b/actionpack/test/controller/new_base/render_layout_test.rb @@ -71,7 +71,8 @@ module ControllerLayouts self.view_paths = [ActionView::FixtureResolver.new( "layouts/application.html.erb" => "<html><%= yield %></html>", "controller_layouts/mismatch_format/index.xml.builder" => "xml.instruct!", - "controller_layouts/mismatch_format/implicit.builder" => "xml.instruct!" + "controller_layouts/mismatch_format/implicit.builder" => "xml.instruct!", + "controller_layouts/mismatch_format/explicit.js.erb" => "alert('foo');" )] def explicit @@ -81,7 +82,7 @@ module ControllerLayouts class MismatchFormatTest < Rack::TestCase testing ControllerLayouts::MismatchFormatController - + XML_INSTRUCT = %Q(<?xml version="1.0" encoding="UTF-8"?>\n) test "if XML is selected, an HTML template is not also selected" do @@ -94,10 +95,33 @@ module ControllerLayouts assert_response XML_INSTRUCT end - test "if an HTML template is explicitly provides for a JS template, an error is raised" do - assert_raises ActionView::MissingTemplate do - get :explicit, {}, "action_dispatch.show_exceptions" => false - end + test "a layout for JS is ignored even if explicitly provided for HTML" do + get :explicit, { :format => "js" } + assert_response "alert('foo');" + end + end + + class FalseLayoutMethodController < ::ApplicationController + self.view_paths = [ActionView::FixtureResolver.new( + "controller_layouts/false_layout_method/index.js.erb" => "alert('foo');" + )] + + layout :which_layout? + + def which_layout? + false + end + + def index + end + end + + class FalseLayoutMethodTest < Rack::TestCase + testing ControllerLayouts::FalseLayoutMethodController + + test "access false layout returned by a method/proc" do + get :index, :format => "js" + assert_response "alert('foo');" end end end diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index 0102f66dfe..c4d2614200 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -147,6 +147,7 @@ class ParamsWrapperTest < ActionController::TestCase end def test_derived_wrapped_keys_from_matching_model + User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).twice.returns(["username"]) @@ -159,6 +160,7 @@ class ParamsWrapperTest < ActionController::TestCase def test_derived_wrapped_keys_from_specified_model with_default_wrapper_options do + Person.expects(:respond_to?).with(:accessible_attributes).returns(false) Person.expects(:respond_to?).with(:attribute_names).returns(true) Person.expects(:attribute_names).twice.returns(["username"]) @@ -169,8 +171,33 @@ class ParamsWrapperTest < ActionController::TestCase assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) end end + + def test_accessible_wrapped_keys_from_matching_model + User.expects(:respond_to?).with(:accessible_attributes).returns(true) + User.expects(:accessible_attributes).twice.returns(["username"]) + + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) + end + end + + def test_accessible_wrapped_keys_from_specified_model + with_default_wrapper_options do + Person.expects(:respond_to?).with(:accessible_attributes).returns(true) + Person.expects(:accessible_attributes).twice.returns(["username"]) + + UsersController.wrap_parameters Person + + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } + assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) + end + end def test_not_wrapping_abstract_model + User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).returns([]) diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index f7411c7729..6133bfe338 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -122,4 +122,17 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest get "/", {}, {'action_dispatch.show_exceptions' => true, 'action_dispatch.backtrace_cleaner' => cleaner} assert_match(/passed backtrace cleaner/, body) end + + test 'logs exception backtrace when all lines silenced' do + output = StringIO.new + backtrace_cleaner = ActiveSupport::BacktraceCleaner.new + backtrace_cleaner.add_silencer { true } + + env = {'action_dispatch.show_exceptions' => true, + 'action_dispatch.logger' => Logger.new(output), + 'action_dispatch.backtrace_cleaner' => backtrace_cleaner} + + get "/", {}, env + assert_operator (output.rewind && output.read).lines.count, :>, 10 + end end diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb index eaabc1feb3..3411bd14ea 100644 --- a/actionpack/test/dispatch/reloader_test.rb +++ b/actionpack/test/dispatch/reloader_test.rb @@ -43,6 +43,19 @@ class ReloaderTest < Test::Unit::TestCase assert_respond_to body, :close end + def test_condition_specifies_when_to_reload + i, j = 0, 0, 0, 0 + Reloader.to_prepare { |*args| i += 1 } + Reloader.to_cleanup { |*args| j += 1 } + app = Reloader.new(lambda { |env| [200, {}, []] }, lambda { i < 3 }) + 5.times do + resp = app.call({}) + resp[2].close + end + assert_equal 3, i + assert_equal 3, j + end + def test_returned_body_object_behaves_like_underlying_object body = call_and_return_body do b = MyBody.new @@ -116,6 +129,15 @@ class ReloaderTest < Test::Unit::TestCase assert cleaned end + def test_prepend_prepare_callback + i = 10 + Reloader.to_prepare { i += 1 } + Reloader.to_prepare(:prepend => true) { i = 0 } + + Reloader.prepare! + assert_equal 1, i + end + def test_cleanup_callbacks_are_called_on_exceptions cleaned = false Reloader.to_cleanup { cleaned = true } diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 5abbaf74fe..9bdd5ecbc6 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -5,6 +5,15 @@ class ResponseTest < ActiveSupport::TestCase @response = ActionDispatch::Response.new end + def test_response_body_encoding + # FIXME: remove this conditional on Rails 4.0 + return unless "<3".encoding_aware? + + body = ["hello".encode('utf-8')] + response = ActionDispatch::Response.new 200, {}, body + assert_equal Encoding::UTF_8, response.body.encoding + end + test "simple output" do @response.body = "Hello, World!" @@ -130,6 +139,17 @@ class ResponseTest < ActiveSupport::TestCase assert_equal('application/xml; charset=utf-16', resp.headers['Content-Type']) end + + test "read content type without charset" do + original = ActionDispatch::Response.default_charset + begin + ActionDispatch::Response.default_charset = 'utf-16' + resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" }) + assert_equal('utf-16', resp.charset) + ensure + ActionDispatch::Response.default_charset = original + end + end end class ResponseIntegrationTest < ActionDispatch::IntegrationTest diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 19eee379fd..bc4e2e31c8 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -2296,7 +2296,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_named_routes_collision_is_avoided_unless_explicitly_given_as assert_equal "/c/1", routes_collision_path(1) - assert_equal "/forced_collision", routes_forced_collision_path + assert_equal "/fc", routes_forced_collision_path end def test_redirect_argument_error diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index af30ec9892..57a5895cec 100644 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -164,6 +164,15 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_day(nil, :include_blank => true) end + def test_select_day_with_two_digit_numbers + expected = %(<select id="date_day" name="date[day]">\n) + expected << %(<option value="1">01</option>\n<option selected="selected" value="2">02</option>\n<option value="3">03</option>\n<option value="4">04</option>\n<option value="5">05</option>\n<option value="6">06</option>\n<option value="7">07</option>\n<option value="8">08</option>\n<option value="9">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_day(Time.mktime(2011, 8, 2), :use_two_digit_numbers => true) + assert_dom_equal expected, select_day(2, :use_two_digit_numbers => true) + end + def test_select_day_with_html_options expected = %(<select id="date_day" name="date[day]" class="selector">\n) expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) @@ -198,6 +207,15 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_month(8) end + def test_select_month_with_two_digit_numbers + expected = %(<select id="date_month" name="date[month]">\n) + expected << %(<option value="1">01</option>\n<option value="2">02</option>\n<option value="3">03</option>\n<option value="4">04</option>\n<option value="5">05</option>\n<option value="6">06</option>\n<option value="7">07</option>\n<option value="8" selected="selected">08</option>\n<option value="9">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_month(Time.mktime(2011, 8, 16), :use_two_digit_numbers => true) + assert_dom_equal expected, select_month(8, :use_two_digit_numbers => true) + end + def test_select_month_with_disabled expected = %(<select id="date_month" name="date[month]" disabled="disabled">\n) expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) @@ -986,7 +1004,6 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :ampm => true) end - def test_select_datetime_with_separators expected = %(<select id="date_first_year" name="date[first][year]">\n) expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 41e925b000..73b936b16e 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -689,6 +689,7 @@ class FormHelperTest < ActionView::TestCase concat f.text_area(:body) concat f.check_box(:secret) concat f.submit('Create post') + concat f.button('Create post') end expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put") do @@ -697,7 +698,8 @@ class FormHelperTest < ActionView::TestCase "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + - "<input name='commit' type='submit' value='Create post' />" + "<input name='commit' type='submit' value='Create post' />" + + "<button name='button' type='submit'>Create post</button>" end assert_dom_equal expected, output_buffer diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 70ca876c67..13d30a93ce 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -170,6 +170,7 @@ class TestERBTemplate < ActiveSupport::TestCase def with_external_encoding(encoding) old = Encoding.default_external + Encoding::Converter.new old, encoding if old != encoding silence_warnings { Encoding.default_external = encoding } yield ensure diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 3caa61e41b..755e54efcd 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -5,7 +5,9 @@ require 'active_support/core_ext/module/deprecation' module ActiveModel class Name < String - attr_reader :singular, :plural, :element, :collection, :partial_path, :route_key, :param_key, :i18n_key + attr_reader :singular, :plural, :element, :collection, :partial_path, + :singular_route_key, :route_key, :param_key, :i18n_key + alias_method :cache_key, :collection deprecate :partial_path => "ActiveModel::Name#partial_path is deprecated. Call #to_partial_path on model instances directly instead." @@ -26,8 +28,12 @@ module ActiveModel @collection = ActiveSupport::Inflector.tableize(self).freeze @partial_path = "#{@collection}/#{@element}".freeze @param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze - @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze @i18n_key = self.underscore.to_sym + + @route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural.dup) + @singular_route_key = ActiveSupport::Inflector.singularize(@route_key).freeze + @route_key << "_index" if @plural == @singular + @route_key.freeze end # Transform the model name into a more humane format, using I18n. By default, @@ -117,10 +123,25 @@ module ActiveModel # namespaced models regarding whether it's inside isolated engine. # # For isolated engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> post + # + # For shared engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> blog_post + def self.singular_route_key(record_or_class) + model_name_from_record_or_class(record_or_class).singular_route_key + end + + # Returns string to use while generating route names. It differs for + # namespaced models regarding whether it's inside isolated engine. + # + # For isolated engine: # ActiveModel::Naming.route_key(Blog::Post) #=> posts # # For shared engine: # ActiveModel::Naming.route_key(Blog::Post) #=> blog_posts + # + # The route key also considers if the noun is uncountable and, in + # such cases, automatically appends _index. def self.route_key(record_or_class) model_name_from_record_or_class(record_or_class).route_key end diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index b2976ab1fb..acda989eec 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -217,6 +217,7 @@ class NamingHelpersTest < Test::Unit::TestCase @singular = 'contact' @plural = 'contacts' @uncountable = Sheep + @singular_route_key = 'contact' @route_key = 'contacts' @param_key = 'contact' end @@ -243,10 +244,12 @@ class NamingHelpersTest < Test::Unit::TestCase def test_route_key assert_equal @route_key, route_key(@record) + assert_equal @singular_route_key, singular_route_key(@record) end def test_route_key_for_class assert_equal @route_key, route_key(@klass) + assert_equal @singular_route_key, singular_route_key(@klass) end def test_param_key @@ -262,6 +265,11 @@ class NamingHelpersTest < Test::Unit::TestCase assert !uncountable?(@klass), "Expected 'contact' to be countable" end + def test_uncountable_route_key + assert_equal "sheep", singular_route_key(@uncountable) + assert_equal "sheep_index", route_key(@uncountable) + end + private def method_missing(method, *args) ActiveModel::Naming.send(method, *args) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 888bc43ec9..cd8e50b33a 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,17 @@ ## Rails 3.2.0 (unreleased) ## +* Added ability to run migrations only for given scope, which allows + to run migrations only from one engine (for example to revert changes + from engine that you want to remove). + + Example: + rake db:migrate SCOPE=blog + + *Piotr Sarnacki* + +* Migrations copied from engines are now scoped with engine's name, + for example 01_create_posts.blog.rb. *Piotr Sarnacki* + * Implements `AR::Base.silence_auto_explain`. This method allows the user to selectively disable automatic EXPLAINs within a block. *fxn* @@ -134,6 +146,10 @@ during :reject_if => :all_blank (fixes #2937) *Aaron Christy* + +* Add ActiveSupport::Cache::NullStore for use in development and testing. + + *Brian Durand* ## Rails 3.1.3 (unreleased) ## diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb index 0f62e819ee..d29af85278 100644 --- a/activerecord/examples/performance.rb +++ b/activerecord/examples/performance.rb @@ -1,6 +1,6 @@ TIMES = (ENV['N'] || 10000).to_i -require 'rubygems' +require File.expand_path('../../../load_paths', __FILE__) require "active_record" conn = { :adapter => 'sqlite3', :database => ':memory:' } diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index a7600a07d8..0efa111d12 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -70,7 +70,7 @@ module ActiveRecord end end - class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc + class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc: def initialize(owner, reflection) super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.") end diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 80bc4990d2..eb320bc774 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -41,8 +41,7 @@ module ActiveRecord delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :pluck, :to => :scoped - delegate :target, :load_target, :loaded?, :scoped, - :to => :@association + delegate :target, :load_target, :loaded?, :to => :@association delegate :select, :find, :first, :last, :build, :create, :create!, @@ -62,6 +61,13 @@ module ActiveRecord @association end + def scoped + association = @association + association.scoped.extending do + define_method(:proxy_association) { association } + end + end + def respond_to?(name, include_private = false) super || (load_target && target.respond_to?(name, include_private)) || diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index c756924186..746682393e 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -72,7 +72,7 @@ module ActiveRecord when :table_name_with_underscore base_name.foreign_key else - if ActiveRecord::Base != self && connection.table_exists?(table_name) + if ActiveRecord::Base != self && connection.schema_cache.table_exists?(table_name) connection.primary_key(table_name) else 'id' diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 8942fab500..25c998e857 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -55,7 +55,7 @@ module ActiveRecord internal = internal_attribute_access_code(attr_name, cast_code) external = external_attribute_access_code(attr_name, cast_code) - generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 def __temp__ #{internal} end @@ -63,7 +63,7 @@ module ActiveRecord undef_method :__temp__ STR - generated_attribute_methods.singleton_class.module_eval <<-STR, __FILE__, __LINE__ + generated_attribute_methods.singleton_class.module_eval <<-STR, __FILE__, __LINE__ + 1 def __temp__(v, attributes, attributes_cache, attr_name) #{external} end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 7ba585b8e0..ba75dc6d09 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -762,7 +762,7 @@ module ActiveRecord #:nodoc: # Indicates whether the table associated with this class exists def table_exists? - connection.table_exists?(table_name) + connection.schema_cache.table_exists?(table_name) end # Returns an array of column objects for the table associated with this class. @@ -2222,8 +2222,6 @@ MSG include AutosaveAssociation, NestedAttributes include Aggregations, Transactions, Reflection, Serialization, Store - NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner) - # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). # (Alias for the protected read_attribute method). diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index ca9fb11e95..7145dc0692 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -127,7 +127,7 @@ module ActiveRecord spec = resolver.spec unless respond_to?(spec.adapter_method) - raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter" + raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter" end remove_connection diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index dc4a53034b..eb8cff9610 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -130,7 +130,7 @@ module ActiveRecord # # In order to get around this problem, #transaction will emulate the effect # of nested transactions, by using savepoints: - # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html + # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html # Savepoints are supported by MySQL and PostgreSQL, but not SQLite3. # # It is safe to call this method if a database transaction is already open, @@ -341,7 +341,7 @@ module ActiveRecord # Send a rollback message to all records after they have been rolled back. If rollback # is false, only rollback records since the last save point. - def rollback_transaction_records(rollback) #:nodoc + def rollback_transaction_records(rollback) if rollback records = @_current_transaction_records.flatten @_current_transaction_records.clear @@ -361,7 +361,7 @@ module ActiveRecord end # Send a commit message to all records after they have been committed. - def commit_transaction_records #:nodoc + def commit_transaction_records records = @_current_transaction_records.flatten @_current_transaction_records.clear unless records.blank? diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 6f135b56b5..132ca10f79 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -66,6 +66,7 @@ module ActiveRecord def initialize(base) @columns = [] + @columns_hash = {} @base = base end @@ -86,7 +87,7 @@ module ActiveRecord # Returns a ColumnDefinition for the column with name +name+. def [](name) - @columns.find {|column| column.name.to_s == name.to_s} + @columns_hash[name.to_s] end # Instantiates a new column for the table. @@ -224,28 +225,31 @@ module ActiveRecord # t.references :taggable, :polymorphic => { :default => 'Photo' } # end def column(name, type, options = {}) - column = self[name] || ColumnDefinition.new(@base, name, type) - if options[:limit] - column.limit = options[:limit] - elsif native[type.to_sym].is_a?(Hash) - column.limit = native[type.to_sym][:limit] + name = name.to_s + type = type.to_sym + + column = self[name] || new_column_definition(@base, name, type) + + limit = options.fetch(:limit) do + native[type][:limit] if native[type].is_a?(Hash) end + + column.limit = limit column.precision = options[:precision] - column.scale = options[:scale] - column.default = options[:default] - column.null = options[:null] - @columns << column unless @columns.include? column + column.scale = options[:scale] + column.default = options[:default] + column.null = options[:null] self end %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type| class_eval <<-EOV, __FILE__, __LINE__ + 1 - def #{column_type}(*args) # def string(*args) - options = args.extract_options! # options = args.extract_options! - column_names = args # column_names = args - # - column_names.each { |name| column(name, '#{column_type}', options) } # column_names.each { |name| column(name, 'string', options) } - end # end + def #{column_type}(*args) # def string(*args) + options = args.extract_options! # options = args.extract_options! + column_names = args # column_names = args + type = :'#{column_type}' # type = :string + column_names.each { |name| column(name, type, options) } # column_names.each { |name| column(name, type, options) } + end # end EOV end @@ -275,9 +279,16 @@ module ActiveRecord end private - def native - @base.native_database_types - end + def new_column_definition(base, name, type) + definition = ColumnDefinition.new base, name, type + @columns << definition + @columns_hash[name] = definition + definition + end + + def native + @base.native_database_types + end end # Represents an SQL table in an abstract way for updating a table. @@ -453,13 +464,13 @@ module ActiveRecord def #{column_type}(*args) # def string(*args) options = args.extract_options! # options = args.extract_options! column_names = args # column_names = args - # + type = :'#{column_type}' # type = :string column_names.each do |name| # column_names.each do |name| - column = ColumnDefinition.new(@base, name, '#{column_type}') # column = ColumnDefinition.new(@base, name, 'string') + column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type) if options[:limit] # if options[:limit] column.limit = options[:limit] # column.limit = options[:limit] - elsif native['#{column_type}'.to_sym].is_a?(Hash) # elsif native['string'.to_sym].is_a?(Hash) - column.limit = native['#{column_type}'.to_sym][:limit] # column.limit = native['string'.to_sym][:limit] + elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash) + column.limit = native[type][:limit] # column.limit = native[type][:limit] end # end column.precision = options[:precision] # column.precision = options[:precision] column.scale = options[:scale] # column.scale = options[:scale] diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 3ced32e42d..a905c135f8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -23,12 +23,10 @@ module ActiveRecord # === Example # table_exists?(:developers) def table_exists?(table_name) - begin - select_value("SELECT 1 FROM #{quote_table_name(table_name)} where 1=0") - true - rescue - false - end + select_value("SELECT 1 FROM #{quote_table_name(table_name)} where 1=0", 'SCHEMA') + true + rescue + false end # Returns an array of indexes for the given table. diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb index b14b37ce89..bee03abd44 100644 --- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb @@ -42,10 +42,7 @@ module ActiveRecord def table_exists?(name) return @tables[name] if @tables.key? name - connection.tables.each { |table| @tables[table] = true } - @tables[name] = connection.table_exists?(name) if !@tables.key?(name) - - @tables[name] + @tables[name] = connection.table_exists?(name) end # Clears out internal caches: @@ -66,6 +63,7 @@ module ActiveRecord @columns_hash.delete table_name @column_defaults.delete table_name @primary_keys.delete table_name + @tables.delete table_name end end end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 386b3f7465..11bb457d03 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -47,11 +47,7 @@ module ActiveRecord # Returns the current database encoding format as a string, eg: 'UTF-8' def encoding - if @connection.respond_to?(:encoding) - @connection.encoding.to_s - else - @connection.execute('PRAGMA encoding')[0]['encoding'] - end + @connection.encoding.to_s end end diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index cad9417216..d8340bf1c9 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -22,8 +22,6 @@ else end end -class FixturesFileNotFound < StandardError; end - module ActiveRecord # \Fixtures are a way of organizing data that you want to test against; in short, sample data. # @@ -644,14 +642,6 @@ module ActiveRecord end def read_fixture_files - if ::File.file?(yaml_file_path) - read_yaml_fixture_files - else - raise FixturesFileNotFound, "Could not find #{yaml_file_path}" - end - end - - def read_yaml_fixture_files yaml_files = Dir["#{@fixture_path}/**/*.yml"].select { |f| ::File.file?(f) } + [yaml_file_path] @@ -832,6 +822,7 @@ module ActiveRecord end @fixture_cache = {} + @fixture_connections = [] @@already_loaded_fixtures ||= {} # Load fixtures once and begin transaction. diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index d70c7d1d34..46464783fd 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -302,7 +302,7 @@ module ActiveRecord # # class TenderloveMigration < ActiveRecord::Migration # def change - # create_table(:horses) do + # create_table(:horses) do |t| # t.column :content, :text # t.column :remind_at, :datetime # end @@ -443,6 +443,7 @@ module ActiveRecord say_with_time "#{method}(#{arg_list})" do unless arguments.empty? || method == :execute arguments[0] = Migrator.proper_table_name(arguments.first) + arguments[1] = Migrator.proper_table_name(arguments.second) if method == :rename_table end return super unless connection.respond_to?(method) connection.send(method, *arguments, &block) @@ -456,26 +457,28 @@ module ActiveRecord destination_migrations = ActiveRecord::Migrator.migrations(destination) last = destination_migrations.last - sources.each do |name, path| + sources.each do |scope, path| source_migrations = ActiveRecord::Migrator.migrations(path) source_migrations.each do |migration| source = File.read(migration.filename) - source = "# This migration comes from #{name} (originally #{migration.version})\n#{source}" + source = "# This migration comes from #{scope} (originally #{migration.version})\n#{source}" if duplicate = destination_migrations.detect { |m| m.name == migration.name } - options[:on_skip].call(name, migration) if File.read(duplicate.filename) != source && options[:on_skip] + if options[:on_skip] && duplicate.scope != scope.to_s + options[:on_skip].call(scope, migration) + end next end migration.version = next_migration_number(last ? last.version + 1 : 0).to_i - new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") + new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.#{scope}.rb") old_path, migration.filename = migration.filename, new_path last = migration - FileUtils.cp(old_path, migration.filename) + File.open(migration.filename, "w") { |f| f.write source } copied << migration - options[:on_copy].call(name, migration, old_path) if options[:on_copy] + options[:on_copy].call(scope, migration, old_path) if options[:on_copy] destination_migrations << migration end end @@ -494,9 +497,9 @@ module ActiveRecord # MigrationProxy is used to defer loading of the actual migration classes # until they are needed - class MigrationProxy < Struct.new(:name, :version, :filename) + class MigrationProxy < Struct.new(:name, :version, :filename, :scope) - def initialize(name, version, filename) + def initialize(name, version, filename, scope) super @migration = nil end @@ -525,16 +528,16 @@ module ActiveRecord attr_writer :migrations_paths alias :migrations_path= :migrations_paths= - def migrate(migrations_paths, target_version = nil) + def migrate(migrations_paths, target_version = nil, &block) case when target_version.nil? - up(migrations_paths, target_version) + up(migrations_paths, target_version, &block) when current_version == 0 && target_version == 0 [] when current_version > target_version - down(migrations_paths, target_version) + down(migrations_paths, target_version, &block) else - up(migrations_paths, target_version) + up(migrations_paths, target_version, &block) end end @@ -546,12 +549,12 @@ module ActiveRecord move(:up, migrations_paths, steps) end - def up(migrations_paths, target_version = nil) - self.new(:up, migrations_paths, target_version).migrate + def up(migrations_paths, target_version = nil, &block) + self.new(:up, migrations_paths, target_version).migrate(&block) end - def down(migrations_paths, target_version = nil) - self.new(:down, migrations_paths, target_version).migrate + def down(migrations_paths, target_version = nil, &block) + self.new(:down, migrations_paths, target_version).migrate(&block) end def run(direction, migrations_paths, target_version) @@ -591,15 +594,16 @@ module ActiveRecord migrations_paths.first end - def migrations(paths) + def migrations(paths, subdirectories = true) paths = Array.wrap(paths) - files = Dir[*paths.map { |p| "#{p}/[0-9]*_*.rb" }] + glob = subdirectories ? "**/" : "" + files = Dir[*paths.map { |p| "#{p}/#{glob}[0-9]*_*.rb" }] seen = Hash.new false migrations = files.map do |file| - version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first + version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first raise IllegalMigrationNameError.new(file) unless version version = version.to_i @@ -610,7 +614,7 @@ module ActiveRecord seen[version] = seen[name] = true - MigrationProxy.new(name, version, file) + MigrationProxy.new(name, version, file, scope) end migrations.sort_by(&:version) @@ -653,7 +657,7 @@ module ActiveRecord end end - def migrate + def migrate(&block) current = migrations.detect { |m| m.version == current_version } target = migrations.detect { |m| m.version == @target_version } @@ -670,6 +674,10 @@ module ActiveRecord ran = [] runnable.each do |migration| + if block && !block.call(migration) + next + end + Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger seen = migrated.include?(migration.version.to_i) diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index c2e31579a4..b28e8da24c 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -94,6 +94,10 @@ module ActiveRecord end end + initializer "active_record.add_watchable_files" do |app| + config.watchable_files.concat ["#{app.root}/db/schema.rb", "#{app.root}/db/structure.sql"] + end + config.after_initialize do ActiveSupport.on_load(:active_record) do instantiate_observers diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index abd71793fd..0aafb5184f 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -149,7 +149,9 @@ db_namespace = namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false)." task :migrate => [:environment, :load_config] do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) + ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration| + ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope) + end db_namespace['_dump'].invoke end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index ae97a3f3ca..2c70d31b94 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -301,7 +301,7 @@ module ActiveRecord protected # Save the new record state and id of a record so it can be restored later if a transaction fails. - def remember_transaction_record_state #:nodoc + def remember_transaction_record_state #:nodoc: @_start_transaction_state ||= {} @_start_transaction_state[:id] = id if has_attribute?(self.class.primary_key) unless @_start_transaction_state.include?(:new_record) @@ -314,7 +314,7 @@ module ActiveRecord end # Clear the new record state and id of a record. - def clear_transaction_record_state #:nodoc + def clear_transaction_record_state #:nodoc: if defined?(@_start_transaction_state) @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 remove_instance_variable(:@_start_transaction_state) if @_start_transaction_state[:level] < 1 @@ -322,7 +322,7 @@ module ActiveRecord end # Restore the new record state and id of a record that was previously saved by a call to save_record_state. - def restore_transaction_record_state(force = false) #:nodoc + def restore_transaction_record_state(force = false) #:nodoc: if defined?(@_start_transaction_state) @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 if @_start_transaction_state[:level] < 1 @@ -341,12 +341,12 @@ module ActiveRecord end # Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed. - def transaction_record_state(state) #:nodoc + def transaction_record_state(state) #:nodoc: @_start_transaction_state[state] if defined?(@_start_transaction_state) end # Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks. - def transaction_include_action?(action) #:nodoc + def transaction_include_action?(action) #:nodoc: case action when :create transaction_record_state(:new_record) diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index 8dc1423375..395b59258d 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -71,6 +71,12 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', extension_name(MyApplication::Business::Developer) end + def test_proxy_association_after_scoped + post = posts(:welcome) + assert_equal post.association(:comments), post.comments.the_association + assert_equal post.association(:comments), post.comments.scoped.the_association + end + private def extension_name(model) diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index b49510b202..745f7132e7 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -825,12 +825,12 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase # clear cache possibly created by other tests david.projects.reset_column_information - # One query for columns, one for primary key - assert_queries(2) { david.projects.columns; david.projects.columns } + # One query for columns, one for primary key, one for table existence + assert_queries(3) { david.projects.columns; david.projects.columns } ## and again to verify that reset_column_information clears the cache correctly david.projects.reset_column_information - assert_queries(2) { david.projects.columns; david.projects.columns } + assert_queries(3) { david.projects.columns; david.projects.columns } end def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 7e2dafcd01..99dd74c561 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -179,7 +179,7 @@ class FixturesTest < ActiveRecord::TestCase #sanity check to make sure that this file never exists assert Dir[nonexistent_fixture_path+"*"].empty? - assert_raise(FixturesFileNotFound) do + assert_raise(Errno::ENOENT) do ActiveRecord::Fixtures.new( Account.connection, "companies", 'Company', nonexistent_fixture_path) end end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 6735bc521b..ae2c230d15 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -68,14 +68,19 @@ module ActiveRecord cattr_accessor :log self.log = [] + attr_reader :ignore + + def initialize(ignore = self.class.ignored_sql) + @ignore = ignore + end + def call(name, start, finish, message_id, values) sql = values[:sql] # FIXME: this seems bad. we should probably have a better way to indicate # the query was cached - unless 'CACHE' == values[:name] - self.class.log << sql unless self.class.ignored_sql.any? { |r| sql =~ r } - end + return if 'CACHE' == values[:name] || ignore.any? { |x| x =~ sql } + self.class.log << sql end end diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb index 9e8475465e..e24a5ca5aa 100644 --- a/activerecord/test/cases/log_subscriber_test.rb +++ b/activerecord/test/cases/log_subscriber_test.rb @@ -13,6 +13,7 @@ class LogSubscriberTest < ActiveRecord::TestCase @old_logger = ActiveRecord::Base.logger @using_identity_map = ActiveRecord::IdentityMap.enabled? ActiveRecord::IdentityMap.enabled = false + Developer.primary_key super ActiveRecord::LogSubscriber.attach_to(:active_record) end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 00c811194c..1e68911ab3 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -6,6 +6,8 @@ require 'models/topic' require 'models/developer' require MIGRATIONS_ROOT + "/valid/2_we_need_reminders" +require MIGRATIONS_ROOT + "/rename/1_we_need_things" +require MIGRATIONS_ROOT + "/rename/2_rename_things" require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers" if ActiveRecord::Base.connection.supports_migrations? @@ -13,6 +15,8 @@ if ActiveRecord::Base.connection.supports_migrations? class Reminder < ActiveRecord::Base; end + class Thing < ActiveRecord::Base; end + class ActiveRecord::Migration class << self attr_accessor :message_count @@ -57,6 +61,11 @@ if ActiveRecord::Base.connection.supports_migrations? ActiveRecord::Base.connection.initialize_schema_migrations_table ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}" + %w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table| + Thing.connection.drop_table(table) rescue nil + end + Thing.reset_column_information + %w(reminders people_reminders prefix_reminders_suffix).each do |table| Reminder.connection.drop_table(table) rescue nil end @@ -1226,6 +1235,24 @@ if ActiveRecord::Base.connection.supports_migrations? assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } end + def test_filtering_migrations + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + + name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" } + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter) + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter) + + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end + class MockMigration < ActiveRecord::Migration attr_reader :went_up, :went_down def initialize @@ -1337,6 +1364,15 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_finds_migrations_in_subdirectories + migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations + + [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i| + assert_equal migrations[i].version, pair.first + assert_equal migrations[i].name, pair.last + end + end + def test_finds_migrations_from_two_directories directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps'] migrations = ActiveRecord::Migrator.new(:up, directories).migrations @@ -1534,6 +1570,28 @@ if ActiveRecord::Base.connection.supports_migrations? Reminder.reset_table_name end + def test_rename_table_with_prefix_and_suffix + assert !Thing.table_exists? + ActiveRecord::Base.table_name_prefix = 'prefix_' + ActiveRecord::Base.table_name_suffix = '_suffix' + Thing.reset_table_name + Thing.reset_sequence_name + WeNeedThings.up + + assert Thing.create("content" => "hello world") + assert_equal "hello world", Thing.find(:first).content + + RenameThings.up + Thing.table_name = "prefix_awesome_things_suffix" + + assert_equal "hello world", Thing.find(:first).content + ensure + ActiveRecord::Base.table_name_prefix = '' + ActiveRecord::Base.table_name_suffix = '' + Thing.reset_table_name + Thing.reset_sequence_name + end + def test_add_drop_table_with_prefix_and_suffix assert !Reminder.table_exists? ActiveRecord::Base.table_name_prefix = 'prefix_' @@ -2068,9 +2126,12 @@ if ActiveRecord::Base.connection.supports_migrations? @existing_migrations = Dir[@migrations_path + "/*.rb"] copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") - assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied.map(&:filename) + assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") + assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename) + + expected = "# This migration comes from bukkits (originally 1)" + assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) @@ -2089,10 +2150,10 @@ if ActiveRecord::Base.connection.supports_migrations? sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy" sources[:omg] = MIGRATIONS_ROOT + "/to_copy2" ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") - assert File.exists?(@migrations_path + "/6_create_articles.rb") - assert File.exists?(@migrations_path + "/7_create_comments.rb") + assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/6_create_articles.omg.rb") + assert File.exists?(@migrations_path + "/7_create_comments.omg.rb") files_count = Dir[@migrations_path + "/*.rb"].length ActiveRecord::Migration.copy(@migrations_path, sources) @@ -2107,10 +2168,10 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") - expected = [@migrations_path + "/20100726101010_people_have_hobbies.rb", - @migrations_path + "/20100726101011_people_have_descriptions.rb"] + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") + expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb", + @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"] assert_equal expected, copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length @@ -2132,10 +2193,10 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") - assert File.exists?(@migrations_path + "/20100726101012_create_articles.rb") - assert File.exists?(@migrations_path + "/20100726101013_create_comments.rb") + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb") + assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb") assert_equal 4, copied.length files_count = Dir[@migrations_path + "/*.rb"].length @@ -2152,8 +2213,8 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.rb") + assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb") files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) @@ -2169,15 +2230,34 @@ if ActiveRecord::Base.connection.supports_migrations? @existing_migrations = Dir[@migrations_path + "/*.rb"] sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision" skipped = [] on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) assert_equal 2, copied.length - assert_equal 2, skipped.length - assert_equal ["bukkits PeopleHaveHobbies", "bukkits PeopleHaveDescriptions"], skipped + assert_equal 1, skipped.length + assert_equal ["omg PeopleHaveHobbies"], skipped + ensure + clear + end + + def test_skip_is_not_called_if_migrations_are_from_the_same_plugin + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + + skipped = [] + on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } + copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + + assert_equal 2, copied.length + assert_equal 0, skipped.length ensure clear end @@ -2188,8 +2268,8 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") assert_equal 2, copied.length end ensure @@ -2203,8 +2283,8 @@ if ActiveRecord::Base.connection.supports_migrations? Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") assert_equal 2, copied.length end ensure diff --git a/activerecord/test/cases/session_store/session_test.rb b/activerecord/test/cases/session_store/session_test.rb index 258cee7aba..c206e3de4a 100644 --- a/activerecord/test/cases/session_store/session_test.rb +++ b/activerecord/test/cases/session_store/session_test.rb @@ -9,6 +9,7 @@ module ActiveRecord def setup super + ActiveRecord::Base.connection.schema_cache.clear! Session.drop_table! if Session.table_exists? end diff --git a/activerecord/test/migrations/rename/1_we_need_things.rb b/activerecord/test/migrations/rename/1_we_need_things.rb new file mode 100644 index 0000000000..cdbe0b1679 --- /dev/null +++ b/activerecord/test/migrations/rename/1_we_need_things.rb @@ -0,0 +1,11 @@ +class WeNeedThings < ActiveRecord::Migration + def self.up + create_table("things") do |t| + t.column :content, :text + end + end + + def self.down + drop_table "things" + end +end
\ No newline at end of file diff --git a/activerecord/test/migrations/rename/2_rename_things.rb b/activerecord/test/migrations/rename/2_rename_things.rb new file mode 100644 index 0000000000..d441b71fc9 --- /dev/null +++ b/activerecord/test/migrations/rename/2_rename_things.rb @@ -0,0 +1,9 @@ +class RenameThings < ActiveRecord::Migration + def self.up + rename_table "things", "awesome_things" + end + + def self.down + rename_table "awesome_things", "things" + end +end
\ No newline at end of file diff --git a/activerecord/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb b/activerecord/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb new file mode 100644 index 0000000000..e438cf5999 --- /dev/null +++ b/activerecord/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb @@ -0,0 +1,9 @@ +class PeopleHaveLastNames < ActiveRecord::Migration + def self.up + add_column "people", "hobbies", :string + end + + def self.down + remove_column "people", "hobbies" + end +end diff --git a/activerecord/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb b/activerecord/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb new file mode 100644 index 0000000000..06cb911117 --- /dev/null +++ b/activerecord/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb @@ -0,0 +1,9 @@ +class ValidPeopleHaveLastNames < ActiveRecord::Migration + def self.up + add_column "people", "last_name", :string + end + + def self.down + remove_column "people", "last_name" + end +end diff --git a/activerecord/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb b/activerecord/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb new file mode 100644 index 0000000000..d5e71ce8ef --- /dev/null +++ b/activerecord/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb @@ -0,0 +1,12 @@ +class WeNeedReminders < ActiveRecord::Migration + def self.up + create_table("reminders") do |t| + t.column :content, :text + t.column :remind_at, :datetime + end + end + + def self.down + drop_table "reminders" + end +end
\ No newline at end of file diff --git a/activerecord/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb b/activerecord/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb new file mode 100644 index 0000000000..21c9ca5328 --- /dev/null +++ b/activerecord/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb @@ -0,0 +1,12 @@ +class InnocentJointable < ActiveRecord::Migration + def self.up + create_table("people_reminders", :id => false) do |t| + t.column :reminder_id, :integer + t.column :person_id, :integer + end + end + + def self.down + drop_table "people_reminders" + end +end
\ No newline at end of file diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 137cee3752..1cab78d8c7 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -44,6 +44,10 @@ class Post < ActiveRecord::Base def newest created.last end + + def the_association + proxy_association + end end has_many :author_favorites, :through => :author @@ -185,4 +189,4 @@ end class SpecialPostWithDefaultScope < ActiveRecord::Base self.table_name = 'posts' default_scope where(:id => [1, 5,6]) -end
\ No newline at end of file +end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 7f1103a6d7..1516472fed 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -47,6 +47,28 @@ * ActiveSupport::OrderedHash now has different behavior for #each and \#each_pair when given a block accepting its parameters with a splat. *Andrew Radev* +* ActiveSupport::BufferedLogger#silence is deprecated. If you want to squelch + logs for a certain block, change the log level for that block. + +* ActiveSupport::BufferedLogger#open_log is deprecated. This method should + not have been public in the first place. + +* ActiveSupport::BufferedLogger's behavior of automatically creating the + directory for your log file is deprecated. Please make sure to create the + directory for your log file before instantiating. + +* ActiveSupport::BufferedLogger#auto_flushing is deprecated. Either set the + sync level on the underlying file handle like this: + + f = File.open('foo.log', 'w') + f.sync = true + ActiveSupport::BufferedLogger.new f + + Or tune your filesystem. The FS cache is now what controls flushing. + +* ActiveSupport::BufferedLogger#flush is deprecated. Set sync on your + filehandle, or tune your filesystem. + ## Rails 3.1.0 (August 30, 2011) ## * ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 136e245859..775f9928e6 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -1,5 +1,9 @@ require 'thread' +require 'logger' +require 'active_support/core_ext/logger' require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/deprecation' +require 'fileutils' module ActiveSupport # Inspired by the buffered logger idea by Ezra @@ -25,40 +29,35 @@ module ActiveSupport # Silences the logger for the duration of the block. def silence(temporary_level = ERROR) if silencer - old_logger_level = @tmp_levels[Thread.current] begin - @tmp_levels[Thread.current] = temporary_level - yield self + logger = self.class.new @log_dest, temporary_level + yield logger ensure - if old_logger_level - @tmp_levels[Thread.current] = old_logger_level - else - @tmp_levels.delete(Thread.current) - end + logger.close end else yield self end end + deprecate :silence - attr_writer :level attr_reader :auto_flushing + deprecate :auto_flushing def initialize(log, level = DEBUG) @level = level - @tmp_levels = {} - @buffer = Hash.new { |h,k| h[k] = [] } - @auto_flushing = 1 - @guard = Mutex.new - - if log.respond_to?(:write) - @log = log - elsif File.exist?(log) - @log = open_log(log, (File::WRONLY | File::APPEND)) - else - FileUtils.mkdir_p(File.dirname(log)) - @log = open_log(log, (File::WRONLY | File::APPEND | File::CREAT)) + @log_dest = log + + unless log.respond_to?(:write) + unless File.exist?(File.dirname(log)) + ActiveSupport::Deprecation.warn(<<-eowarn) +Automatic directory creation for '#{log}' is deprecated. Please make sure the directory for your log file exists before creating the logger. + eowarn + FileUtils.mkdir_p(File.dirname(log)) + end end + + @log = open_logfile log end def open_log(log, mode) @@ -67,20 +66,18 @@ module ActiveSupport open_log.sync = true end end + deprecate :open_log def level - @tmp_levels[Thread.current] || @level + @log.level + end + + def level=(l) + @log.level = l end def add(severity, message = nil, progname = nil, &block) - return if level > severity - message = (message || (block && block.call) || progname).to_s - # If a newline is necessary then create a new message ending with a newline. - # Ensures that the original message is not mutated. - message = "#{message}\n" unless message[-1] == ?\n - buffer << message - auto_flush - message + @log.add(severity, message, progname, &block) end # Dynamically add methods such as: @@ -104,62 +101,25 @@ module ActiveSupport # never auto-flush. If you turn auto-flushing off, be sure to regularly # flush the log yourself -- it will eat up memory until you do. def auto_flushing=(period) - @auto_flushing = - case period - when true; 1 - when false, nil, 0; MAX_BUFFER_SIZE - when Integer; period - else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}" - end end + deprecate :auto_flushing= def flush - @guard.synchronize do - write_buffer(buffer) - - # Important to do this even if buffer was empty or else @buffer will - # accumulate empty arrays for each request where nothing was logged. - clear_buffer + end + deprecate :flush - # Clear buffers associated with dead threads or else spawned threads - # that don't call flush will result in a memory leak. - flush_dead_buffers - end + def respond_to?(method, include_private = false) + return false if method.to_s == "flush" + super end def close - flush - @log.close if @log.respond_to?(:close) - @log = nil + @log.close end - protected - def auto_flush - flush if buffer.size >= @auto_flushing - end - - def buffer - @buffer[Thread.current] - end - - def clear_buffer - @buffer.delete(Thread.current) - end - - # Find buffers created by threads that are no longer alive and flush them to the log - # in order to prevent memory leaks from spawned threads. - def flush_dead_buffers #:nodoc: - @buffer.keys.reject{|thread| thread.alive?}.each do |thread| - buffer = @buffer[thread] - write_buffer(buffer) - @buffer.delete(thread) - end - end - - def write_buffer(buffer) - buffer.each do |content| - @log.write(content) - end - end + private + def open_logfile(log) + Logger.new log + end end end diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 07f5fcdeb3..9711ed6f73 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -16,6 +16,7 @@ module ActiveSupport autoload :FileStore, 'active_support/cache/file_store' autoload :MemoryStore, 'active_support/cache/memory_store' autoload :MemCacheStore, 'active_support/cache/mem_cache_store' + autoload :NullStore, 'active_support/cache/null_store' # These options mean something to all cache implementations. Individual cache # implementations may support additional options. diff --git a/activesupport/lib/active_support/cache/null_store.rb b/activesupport/lib/active_support/cache/null_store.rb new file mode 100644 index 0000000000..4427eaafcd --- /dev/null +++ b/activesupport/lib/active_support/cache/null_store.rb @@ -0,0 +1,44 @@ +module ActiveSupport + module Cache + # A cache store implementation which doesn't actually store anything. Useful in + # development and test environments where you don't want caching turned on but + # need to go through the caching interface. + # + # This cache does implement the local cache strategy, so values will actually + # be cached inside blocks that utilize this strategy. See + # ActiveSupport::Cache::Strategy::LocalCache for more details. + class NullStore < Store + def initialize(options = nil) + super(options) + extend Strategy::LocalCache + end + + def clear(options = nil) + end + + def cleanup(options = nil) + end + + def increment(name, amount = 1, options = nil) + end + + def decrement(name, amount = 1, options = nil) + end + + def delete_matched(matcher, options = nil) + end + + protected + def read_entry(key, options) # :nodoc: + end + + def write_entry(key, entry, options) # :nodoc: + true + end + + def delete_entry(key, options) # :nodoc: + false + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index aae1cfccf2..400db2ce39 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -44,7 +44,7 @@ class String end end - def is_utf8? #:nodoc + def is_utf8? case encoding when Encoding::UTF_8 valid_encoding? diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 7b359a039b..c6d861d124 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -6,21 +6,33 @@ class ERB HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } - # A utility method for escaping HTML tag characters. - # This method is also aliased as <tt>h</tt>. - # - # In your ERB templates, use this method to escape any unsafe content. For example: - # <%=h @person.name %> - # - # ==== Example: - # puts html_escape("is a > 0 & a < 10?") - # # => is a > 0 & a < 10? - def html_escape(s) - s = s.to_s - if s.html_safe? - s - else - s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe + # Detect whether 1.9 can transcode with XML escaping. + if '"><&""' == ('><&"'.encode('utf-8', :xml => :attr) rescue false) + # A utility method for escaping HTML tag characters. + # This method is also aliased as <tt>h</tt>. + # + # In your ERB templates, use this method to escape any unsafe content. For example: + # <%=h @person.name %> + # + # ==== Example: + # puts html_escape("is a > 0 & a < 10?") + # # => is a > 0 & a < 10? + def html_escape(s) + s = s.to_s + if s.html_safe? + s + else + s.encode(s.encoding, :xml => :attr)[1...-1].html_safe + end + end + else + def html_escape(s) #:nodoc: + s = s.to_s + if s.html_safe? + s + else + s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe + end end end diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 989c7205fa..43dd22654a 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -87,6 +87,10 @@ module ActiveSupport #:nodoc: @stack.each(&block) end + def watching? + !@watching.empty? + end + # return a list of new constants found since the last call to watch_namespaces def new_constants constants = [] @@ -226,7 +230,7 @@ module ActiveSupport #:nodoc: end def load_dependency(file) - if Dependencies.load? + if Dependencies.load? && ActiveSupport::Dependencies.constant_watch_stack.watching? Dependencies.new_constants_in(Object) { yield } else yield diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index f76ddff038..a4ad2da137 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,8 +1,28 @@ +require "active_support/core_ext/array/wrap" +require "active_support/core_ext/array/extract_options" + module ActiveSupport - # This class is responsible to track files and invoke the given block - # whenever one of these files are changed. For example, this class - # is used by Rails to reload the I18n framework whenever they are - # changed upon a new request. + # \FileUpdateChecker specifies the API used by Rails to watch files + # and control reloading. The API depends on four methods: + # + # * +initialize+ which expects two parameters and one block as + # described below; + # + # * +updated?+ which returns a boolean if there were updates in + # the filesystem or not; + # + # * +execute+ which executes the given block on initialization + # and updates the counter to the latest timestamp; + # + # * +execute_if_updated+ which just executes the block if it was updated; + # + # After initialization, a call to +execute_if_updated+ must execute + # the block only if there was really a change in the filesystem. + # + # == Examples + # + # This class is used by Rails to reload the I18n framework whenever + # they are changed upon a new request. # # i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do # I18n.reload! @@ -13,24 +33,89 @@ module ActiveSupport # end # class FileUpdateChecker - attr_reader :paths, :last_update_at - - def initialize(paths, calculate=false, &block) - @paths = paths + # It accepts two parameters on initialization. The first is an array + # of files and the second is an optional hash of directories. The hash must + # have directories as keys and the value is an array of extensions to be + # watched under that directory. + # + # This method must also receive a block that will be called once a path changes. + # + # == Implementation details + # + # This particular implementation checks for added and updated files, + # but not removed files. Directories lookup are compiled to a glob for + # performance. Therefore, while someone can add new files to the +files+ + # array after initialization (and parts of Rails do depend on this feature), + # adding new directories after initialization is not allowed. + # + # Notice that other objects that implements FileUpdateChecker API may + # not even allow new files to be added after initialization. If this + # is the case, we recommend freezing the +files+ after initialization to + # avoid changes that won't make effect. + def initialize(files, dirs={}, &block) + @files = files + @glob = compile_glob(dirs) @block = block - @last_update_at = calculate ? updated_at : nil + @updated_at = nil + @last_update_at = updated_at + end + + # Check if any of the entries were updated. If so, the updated_at + # value is cached until the block is executed via +execute+ or +execute_if_updated+ + def updated? + current_updated_at = updated_at + if @last_update_at < current_updated_at + @updated_at = updated_at + true + else + false + end end - def updated_at - paths.map { |path| File.mtime(path) }.max + # Executes the given block and updates the counter to latest timestamp. + def execute + @last_update_at = updated_at + @block.call + ensure + @updated_at = nil end + # Execute the block given if updated. def execute_if_updated - current_update_at = self.updated_at - if @last_update_at != current_update_at - @last_update_at = current_update_at - @block.call + if updated? + execute + true + else + false + end + end + + private + + def updated_at #:nodoc: + @updated_at || begin + all = [] + all.concat @files.select { |f| File.exists?(f) } + all.concat Dir[@glob] if @glob + all.map { |path| File.mtime(path) }.max || Time.at(0) end end + + def compile_glob(hash) #:nodoc: + hash.freeze # Freeze so changes aren't accidently pushed + return if hash.empty? + + globs = [] + hash.each do |key, value| + globs << "#{key}/**/*#{compile_ext(value)}" + end + "{#{globs.join(",")}}" + end + + def compile_ext(array) #:nodoc: + array = Array.wrap(array) + return if array.empty? + ".{#{array.join(",")}}" + end end end diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 636f019cd5..674e4acfd6 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -16,6 +16,10 @@ module ActiveSupport dup end + def nested_under_indifferent_access + self + end + def initialize(constructor = {}) if constructor.is_a?(Hash) super() diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb index 4c59fe9ac9..bbeb8d82c6 100644 --- a/activesupport/lib/active_support/i18n_railtie.rb +++ b/activesupport/lib/active_support/i18n_railtie.rb @@ -10,14 +10,19 @@ module I18n config.i18n.fallbacks = ActiveSupport::OrderedOptions.new def self.reloader - @reloader ||= ActiveSupport::FileUpdateChecker.new([]){ I18n.reload! } + @reloader ||= ActiveSupport::FileUpdateChecker.new(reloader_paths){ I18n.reload! } + end + + def self.reloader_paths + @reloader_paths ||= [] end # Add <tt>I18n::Railtie.reloader</tt> to ActionDispatch callbacks. Since, at this # point, no path was added to the reloader, I18n.reload! is not triggered # on to_prepare callbacks. This will only happen on the config.after_initialize # callback below. - initializer "i18n.callbacks" do + initializer "i18n.callbacks" do |app| + app.reloaders << I18n::Railtie.reloader ActionDispatch::Reloader.to_prepare do I18n::Railtie.reloader.execute_if_updated end @@ -58,8 +63,8 @@ module I18n init_fallbacks(fallbacks) if fallbacks && validate_fallbacks(fallbacks) - reloader.paths.concat I18n.load_path - reloader.execute_if_updated + reloader_paths.concat I18n.load_path + reloader.execute @i18n_inited = true end diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index daf2a1e1d9..527cce2594 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -16,8 +16,8 @@ module ActiveSupport inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies') inflect.plural(/(x|ch|ss|sh)$/i, '\1es') inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices') - inflect.plural(/([m|l])ouse$/i, '\1ice') - inflect.plural(/([m|l])ice$/i, '\1ice') + inflect.plural(/(m|l)ouse$/i, '\1ice') + inflect.plural(/(m|l)ice$/i, '\1ice') inflect.plural(/^(ox)$/i, '\1en') inflect.plural(/^(oxen)$/i, '\1') inflect.plural(/(quiz)$/i, '\1zes') @@ -35,7 +35,7 @@ module ActiveSupport inflect.singular(/(s)eries$/i, '\1eries') inflect.singular(/(m)ovies$/i, '\1ovie') inflect.singular(/(x|ch|ss|sh)es$/i, '\1') - inflect.singular(/([m|l])ice$/i, '\1ouse') + inflect.singular(/(m|l)ice$/i, '\1ouse') inflect.singular(/(bus)es$/i, '\1') inflect.singular(/(o)es$/i, '\1') inflect.singular(/(shoe)s$/i, '\1') diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb index 63e8837a07..0f3ac0c132 100644 --- a/activesupport/lib/active_support/tagged_logging.rb +++ b/activesupport/lib/active_support/tagged_logging.rb @@ -38,9 +38,9 @@ module ActiveSupport EOM end - def flush(*args) + def flush @tags.delete(Thread.current) - @logger.flush(*args) if @logger.respond_to?(:flush) + @logger.flush if @logger.respond_to?(:flush) end def method_missing(method, *args) diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb index 577db5018e..a065233679 100644 --- a/activesupport/lib/active_support/whiny_nil.rb +++ b/activesupport/lib/active_support/whiny_nil.rb @@ -1,21 +1,6 @@ # Extensions to +nil+ which allow for more helpful error messages for people who # are new to Rails. # -# Ruby raises NoMethodError if you invoke a method on an object that does not -# respond to it: -# -# $ ruby -e nil.destroy -# -e:1: undefined method `destroy' for nil:NilClass (NoMethodError) -# -# With these extensions, if the method belongs to the public interface of the -# classes in NilClass::WHINERS the error message suggests which could be the -# actual intended class: -# -# $ rails runner nil.destroy -# ... -# You might have expected an instance of ActiveRecord::Base. -# ... -# # NilClass#id exists in Ruby 1.8 (though it is deprecated). Since +id+ is a fundamental # method of Active Record models NilClass#id is redefined as well to raise a RuntimeError # and warn the user. She probably wanted a model database identifier and the 4 @@ -25,36 +10,13 @@ # By default it is on in development and test modes, and it is off in production # mode. class NilClass - METHOD_CLASS_MAP = Hash.new - def self.add_whiner(klass) - methods = klass.public_instance_methods - public_instance_methods - class_name = klass.name - methods.each { |method| METHOD_CLASS_MAP[method.to_sym] = class_name } + ActiveSupport::Deprecation.warn "NilClass.add_whiner is deprecated and this functionality is " \ + "removed from Rails versions as it affects Ruby 1.9 performance.", caller end - add_whiner ::Array - # Raises a RuntimeError when you attempt to call +id+ on +nil+. def id raise RuntimeError, "Called id for nil, which would mistakenly be #{object_id} -- if you really wanted the id of nil, use object_id", caller end - - private - def method_missing(method, *args) - if klass = METHOD_CLASS_MAP[method] - raise_nil_warning_for klass, method, caller - else - super - end - end - - # Raises a NoMethodError when you attempt to call a method on +nil+. - def raise_nil_warning_for(class_name = nil, selector = nil, with_caller = nil) - message = "You have a nil object when you didn't expect it!" - message << "\nYou might have expected an instance of #{class_name}." if class_name - message << "\nThe error occurred while evaluating nil.#{selector}" if selector - - raise NoMethodError, message, with_caller || caller - end end diff --git a/activesupport/test/benchmarkable_test.rb b/activesupport/test/benchmarkable_test.rb index 06f5172e1f..24b5b5bee1 100644 --- a/activesupport/test/benchmarkable_test.rb +++ b/activesupport/test/benchmarkable_test.rb @@ -3,8 +3,23 @@ require 'abstract_unit' class BenchmarkableTest < ActiveSupport::TestCase include ActiveSupport::Benchmarkable - def teardown - logger.send(:clear_buffer) + attr_reader :buffer, :logger + + class Buffer + include Enumerable + + def initialize; @lines = []; end + def each(&block); @lines.each(&block); end + def write(x); @lines << x; end + def close; end + def last; @lines.last; end + def size; @lines.size; end + def empty?; @lines.empty?; end + end + + def setup + @buffer = Buffer.new + @logger = ActiveSupport::BufferedLogger.new(@buffer) end def test_without_block @@ -40,35 +55,7 @@ class BenchmarkableTest < ActiveSupport::TestCase logger.level = ActiveSupport::BufferedLogger::DEBUG end - def test_without_silencing - benchmark('debug_run', :silence => false) do - logger.info "not silenced!" - end - - assert_equal 2, buffer.size - end - - def test_with_silencing - benchmark('debug_run', :silence => true) do - logger.info "silenced!" - end - - assert_equal 1, buffer.size - end - private - def logger - @logger ||= begin - logger = ActiveSupport::BufferedLogger.new(StringIO.new) - logger.auto_flushing = false - logger - end - end - - def buffer - logger.send(:buffer) - end - def assert_last_logged(message = 'Benchmarking') assert_match(/^#{message} \(.*\)$/, buffer.last) end diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb index 386006677b..f975685ca5 100644 --- a/activesupport/test/buffered_logger_test.rb +++ b/activesupport/test/buffered_logger_test.rb @@ -4,9 +4,11 @@ require 'stringio' require 'fileutils' require 'tempfile' require 'active_support/buffered_logger' +require 'active_support/testing/deprecation' class BufferedLoggerTest < Test::Unit::TestCase include MultibyteTestHelpers + include ActiveSupport::Testing::Deprecation Logger = ActiveSupport::BufferedLogger @@ -23,7 +25,10 @@ class BufferedLoggerTest < Test::Unit::TestCase t.write 'hi mom!' t.close - logger = Logger.new t.path + f = File.open(t.path, 'w') + f.binmode + + logger = Logger.new f logger.level = Logger::DEBUG str = "\x80" @@ -32,7 +37,6 @@ class BufferedLoggerTest < Test::Unit::TestCase end logger.add Logger::DEBUG, str - logger.flush ensure logger.close t.close true @@ -40,7 +44,11 @@ class BufferedLoggerTest < Test::Unit::TestCase def test_write_binary_data_create_file fname = File.join Dir.tmpdir, 'lol', 'rofl.log' - logger = Logger.new fname + FileUtils.mkdir_p File.dirname(fname) + f = File.open(fname, 'w') + f.binmode + + logger = Logger.new f logger.level = Logger::DEBUG str = "\x80" @@ -49,7 +57,6 @@ class BufferedLoggerTest < Test::Unit::TestCase end logger.add Logger::DEBUG, str - logger.flush ensure logger.close File.unlink fname @@ -104,34 +111,6 @@ class BufferedLoggerTest < Test::Unit::TestCase assert_equal message_copy, @message end - - [false, nil, 0].each do |disable| - define_method "test_disabling_auto_flush_with_#{disable.inspect}_should_buffer_until_explicit_flush" do - @logger.auto_flushing = disable - - 4.times do - @logger.info 'wait for it..' - assert @output.string.empty?, "@output.string should be empty but it is #{@output.string}" - end - - @logger.flush - assert !@output.string.empty?, "@logger.send(:buffer).size.to_s should not be empty but it is empty" - end - - define_method "test_disabling_auto_flush_with_#{disable.inspect}_should_flush_at_max_buffer_size_as_failsafe" do - @logger.auto_flushing = disable - assert_equal Logger::MAX_BUFFER_SIZE, @logger.auto_flushing - - (Logger::MAX_BUFFER_SIZE - 1).times do - @logger.info 'wait for it..' - assert @output.string.empty?, "@output.string should be empty but is #{@output.string}" - end - - @logger.info 'there it is.' - assert !@output.string.empty?, "@logger.send(:buffer).size.to_s should not be empty but it is empty" - end - end - def test_should_know_if_its_loglevel_is_below_a_given_level Logger::Severity.constants.each do |level| @logger.level = Logger::Severity.const_get(level) - 1 @@ -139,56 +118,17 @@ class BufferedLoggerTest < Test::Unit::TestCase end end - def test_should_auto_flush_every_n_messages - @logger.auto_flushing = 5 - - 4.times do - @logger.info 'wait for it..' - assert @output.string.empty?, "@output.string should be empty but it is #{@output.string}" - end - - @logger.info 'there it is.' - assert !@output.string.empty?, "@output.string should not be empty but it is empty" - end - def test_should_create_the_log_directory_if_it_doesnt_exist tmp_directory = File.join(File.dirname(__FILE__), "tmp") log_file = File.join(tmp_directory, "development.log") FileUtils.rm_rf(tmp_directory) - @logger = Logger.new(log_file) - assert File.exist?(tmp_directory) - end - - def test_logger_should_maintain_separate_buffers_for_each_thread - @logger.auto_flushing = false - - a = Thread.new do - @logger.info("a"); Thread.pass; - @logger.info("b"); Thread.pass; - @logger.info("c"); @logger.flush - end - - b = Thread.new do - @logger.info("x"); Thread.pass; - @logger.info("y"); Thread.pass; - @logger.info("z"); @logger.flush + assert_deprecated do + @logger = Logger.new(log_file) end - - a.join - b.join - - assert @output.string.include?("a\nb\nc\n") - assert @output.string.include?("x\ny\nz\n") - end - - def test_flush_should_remove_empty_buffers - @logger.send :buffer - @logger.expects :clear_buffer - @logger.flush + assert File.exist?(tmp_directory) end def test_buffer_multibyte - @logger.auto_flushing = 2 @logger.info(UNICODE_STRING) @logger.info(BYTE_STRING) assert @output.string.include?(UNICODE_STRING) @@ -198,57 +138,4 @@ class BufferedLoggerTest < Test::Unit::TestCase end assert byte_string.include?(BYTE_STRING) end - - def test_silence_only_current_thread - @logger.auto_flushing = true - run_thread_a = false - - a = Thread.new do - while !run_thread_a do - sleep(0.001) - end - @logger.info("x") - run_thread_a = false - end - - @logger.silence do - run_thread_a = true - @logger.info("a") - while run_thread_a do - sleep(0.001) - end - end - - a.join - - assert @output.string.include?("x") - assert !@output.string.include?("a") - end - - def test_flush_dead_buffers - @logger.auto_flushing = false - - a = Thread.new do - @logger.info("a") - end - - keep_running = true - Thread.new do - @logger.info("b") - while keep_running - sleep(0.001) - end - end - - @logger.info("x") - a.join - @logger.flush - - - assert @output.string.include?("x") - assert @output.string.include?("a") - assert !@output.string.include?("b") - - keep_running = false - end end diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 5d7464c623..ab29ddecc5 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -218,7 +218,7 @@ module CacheStoreBehavior @cache.write('fud', 'biz') assert_equal({"foo" => "bar", "fu" => "baz"}, @cache.read_multi('foo', 'fu')) end - + def test_read_multi_with_expires @cache.write('foo', 'bar', :expires_in => 0.001) @cache.write('fu', 'baz') @@ -576,12 +576,12 @@ class FileStoreTest < ActiveSupport::TestCase key = @cache_with_pathname.send(:key_file_path, "views/index?id=1") assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key) end - + # Because file systems have a maximum filename size, filenames > max size should be split in to directories # If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B def test_key_transformation_max_filename_size key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B" - path = @cache.send(:key_file_path, key) + path = @cache.send(:key_file_path, key) assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE} assert_equal 'B', File.basename(path) end @@ -689,14 +689,14 @@ uses_memcached 'memcached backed store' do cache.write("foo", 2) assert_equal "2", cache.read("foo") end - + def test_raw_values_with_marshal cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true) cache.clear cache.write("foo", Marshal.dump([])) - assert_equal [], cache.read("foo") + assert_equal [], cache.read("foo") end - + def test_local_cache_raw_values cache = ActiveSupport::Cache.lookup_store(:mem_cache_store, :raw => true) cache.clear @@ -717,6 +717,64 @@ uses_memcached 'memcached backed store' do end end +class NullStoreTest < ActiveSupport::TestCase + def setup + @cache = ActiveSupport::Cache.lookup_store(:null_store) + end + + def test_clear + @cache.clear + end + + def test_cleanup + @cache.cleanup + end + + def test_write + assert_equal true, @cache.write("name", "value") + end + + def test_read + @cache.write("name", "value") + assert_nil @cache.read("name") + end + + def test_delete + @cache.write("name", "value") + assert_equal false, @cache.delete("name") + end + + def test_increment + @cache.write("name", 1, :raw => true) + assert_nil @cache.increment("name") + end + + def test_decrement + @cache.write("name", 1, :raw => true) + assert_nil @cache.increment("name") + end + + def test_delete_matched + @cache.write("name", "value") + @cache.delete_matched(/name/) + end + + def test_local_store_strategy + @cache.with_local_cache do + @cache.write("name", "value") + assert_equal "value", @cache.read("name") + @cache.delete("name") + assert_nil @cache.read("name") + @cache.write("name", "value") + end + assert_nil @cache.read("name") + end + + def test_setting_nil_cache_store + assert ActiveSupport::Cache.lookup_store.class.name, ActiveSupport::Cache::NullStore.name + end +end + class CacheStoreLoggerTest < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:memory_store) diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index fa800eada2..eb8ed761da 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -121,6 +121,9 @@ class HashExtTest < Test::Unit::TestCase foo = { "foo" => NonIndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access assert_kind_of NonIndifferentHash, foo["foo"] + + foo = { "foo" => IndifferentHash.new.tap { |h| h["bar"] = "baz" } }.with_indifferent_access + assert_kind_of IndifferentHash, foo["foo"] end def test_indifferent_assorted diff --git a/activesupport/test/file_update_checker_test.rb b/activesupport/test/file_update_checker_test.rb index b65bb1d024..dd19b58aa2 100644 --- a/activesupport/test/file_update_checker_test.rb +++ b/activesupport/test/file_update_checker_test.rb @@ -4,15 +4,17 @@ require 'fileutils' MTIME_FIXTURES_PATH = File.expand_path("../fixtures", __FILE__) -class FileUpdateCheckerTest < Test::Unit::TestCase +class FileUpdateCheckerWithEnumerableTest < Test::Unit::TestCase FILES = %w(1.txt 2.txt 3.txt) def setup + FileUtils.mkdir_p("tmp_watcher") FileUtils.touch(FILES) end def teardown - FileUtils.rm(FILES) + FileUtils.rm_rf("tmp_watcher") + FileUtils.rm_rf(FILES) end def test_should_not_execute_the_block_if_no_paths_are_given @@ -22,34 +24,60 @@ class FileUpdateCheckerTest < Test::Unit::TestCase assert_equal 0, i end - def test_should_invoke_the_block_on_first_call_if_it_does_not_calculate_last_updated_at_on_load + def test_should_not_invoke_the_block_if_no_file_has_changed i = 0 checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } - checker.execute_if_updated - assert_equal 1, i + 5.times { assert !checker.execute_if_updated } + assert_equal 0, i end - def test_should_not_invoke_the_block_on_first_call_if_it_calculates_last_updated_at_on_load + def test_should_invoke_the_block_if_a_file_has_changed i = 0 - checker = ActiveSupport::FileUpdateChecker.new(FILES, true){ i += 1 } - checker.execute_if_updated - assert_equal 0, i + checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } + sleep(1) + FileUtils.touch(FILES) + assert checker.execute_if_updated + assert_equal 1, i end - def test_should_not_invoke_the_block_if_no_file_has_changed + def test_should_be_robust_enough_to_handle_deleted_files i = 0 checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } - 5.times { checker.execute_if_updated } - assert_equal 1, i + FileUtils.rm(FILES) + assert !checker.execute_if_updated + assert_equal 0, i end - def test_should_invoke_the_block_if_a_file_has_changed + def test_should_cache_updated_result_until_execute i = 0 checker = ActiveSupport::FileUpdateChecker.new(FILES){ i += 1 } - checker.execute_if_updated + assert !checker.updated? + sleep(1) FileUtils.touch(FILES) - checker.execute_if_updated - assert_equal 2, i + + assert checker.updated? + checker.execute + assert !checker.updated? + end + + def test_should_invoke_the_block_if_a_watched_dir_changed_its_glob + i = 0 + checker = ActiveSupport::FileUpdateChecker.new([], "tmp_watcher" => [:txt]){ i += 1 } + FileUtils.cd "tmp_watcher" do + FileUtils.touch(FILES) + end + assert checker.execute_if_updated + assert_equal 1, i + end + + def test_should_not_invoke_the_block_if_a_watched_dir_changed_its_glob + i = 0 + checker = ActiveSupport::FileUpdateChecker.new([], "tmp_watcher" => :rb){ i += 1 } + FileUtils.cd "tmp_watcher" do + FileUtils.touch(FILES) + end + assert !checker.execute_if_updated + assert_equal 0, i end -end +end
\ No newline at end of file diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb index e3a343af52..eb2915c286 100644 --- a/activesupport/test/inflector_test_cases.rb +++ b/activesupport/test/inflector_test_cases.rb @@ -104,7 +104,11 @@ module InflectorTestCases "edge" => "edges", "cow" => "kine", - "database" => "databases" + "database" => "databases", + + # regression tests against improper inflection regexes + "|ice" => "|ices", + "|ouse" => "|ouses" } CamelToUnderscore = { diff --git a/activesupport/test/whiny_nil_test.rb b/activesupport/test/whiny_nil_test.rb index 1acaf7228f..8c1f1b2677 100644 --- a/activesupport/test/whiny_nil_test.rb +++ b/activesupport/test/whiny_nil_test.rb @@ -1,54 +1,11 @@ -# Stub to enable testing without Active Record -module ActiveRecord - class Base - def save! - end - end -end - require 'abstract_unit' require 'active_support/whiny_nil' -NilClass.add_whiner ::ActiveRecord::Base - class WhinyNilTest < Test::Unit::TestCase - def test_unchanged - nil.method_thats_not_in_whiners - rescue NoMethodError => nme - assert_match(/nil:NilClass/, nme.message) - end - - def test_active_record - nil.save! - rescue NoMethodError => nme - assert_no_match(/nil:NilClass/, nme.message) - assert_match(/nil\.save!/, nme.message) - end - - def test_array - nil.each - rescue NoMethodError => nme - assert_no_match(/nil:NilClass/, nme.message) - assert_match(/nil\.each/, nme.message) - end - def test_id nil.id rescue RuntimeError => nme assert_no_match(/nil:NilClass/, nme.message) assert_match(Regexp.new(nil.object_id.to_s), nme.message) end - - def test_no_to_ary_coercion - nil.to_ary - rescue NoMethodError => nme - assert_no_match(/nil:NilClass/, nme.message) - assert_match(/nil\.to_ary/, nme.message) - end - - def test_no_to_str_coercion - nil.to_str - rescue NoMethodError => nme - assert_match(/nil:NilClass/, nme.message) - end end diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 2841996b56..a88f443517 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,9 +1,8 @@ ## Rails 3.2.0 (unreleased) ## -* New applications get a flag - `config.active_record.auto_explain_threshold_in_seconds` in the environments - configuration files. With a value of 0.5 in development.rb, and commented - out in production.rb. No mention in test.rb. *fxn* +* Speed up development by only reloading classes if dependencies files changed. This can be turned off by setting `config.reload_classes_only_on_change` to false. *José Valim* + +* New applications get a flag `config.active_record.auto_explain_threshold_in_seconds` in the environments configuration files. With a value of 0.5 in development.rb, and commented out in production.rb. No mention in test.rb. *fxn* * Add DebugExceptions middleware which contains features extracted from ShowExceptions middleware *José Valim* diff --git a/railties/guides/code/getting_started/README b/railties/guides/code/getting_started/README.rdoc index 7c36f2356e..7c36f2356e 100644 --- a/railties/guides/code/getting_started/README +++ b/railties/guides/code/getting_started/README.rdoc diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile index 15ae145c22..f48f5afd54 100644 --- a/railties/guides/source/asset_pipeline.textile +++ b/railties/guides/source/asset_pipeline.textile @@ -369,10 +369,10 @@ It is important that this folder is shared between deployments so that remotely NOTE. If you are precompiling your assets locally, you can use +bundle install --without assets+ on the server to avoid installing the assets gems (the gems in the assets group in the Gemfile). -The default matcher for compiling files includes +application.js+, +application.css+ and all files that do not end in +js+ or +css+: +The default matcher for compiling files includes +application.js+, +application.css+ and all non-JS/CSS files (ie. +.coffee+ and +.scss+ files are *not* automatically included as they compile to JS/CSS): <ruby> -[ /\w<plus>\.(?!js|css).<plus>/, /application.(css|js)$/ ] +[ Proc.new{ |path| !File.extname(path).in?(['.js', '.css']) }, /application.(css|js)$/ ] </ruby> If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the +precompile+ array: diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile index 0ef6f51190..ec9bfd4d40 100644 --- a/railties/guides/source/caching_with_rails.textile +++ b/railties/guides/source/caching_with_rails.textile @@ -332,6 +332,14 @@ caches_action :index, :expires_in => 60.seconds, :unless_exist => true For more information about Ehcache, see "http://ehcache.org/":http://ehcache.org/ . For more information about Ehcache for JRuby and Rails, see "http://ehcache.org/documentation/jruby.html":http://ehcache.org/documentation/jruby.html +h4. ActiveSupport::Cache::NullStore + +This cache store implementation is meant to be used only in development or test environments and it never stores anything. This can be very useful in development when you have code that interacts directly with +Rails.cache+, but caching may interfere with being able to see the results of code changes. With this cache store, all +fetch+ and +read+ operations will result in a miss. + +<ruby> +ActionController::Base.cache_store = :null +</ruby> + h4. Custom Cache Stores You can create your own custom cache store by simply extending +ActiveSupport::Cache::Store+ and implementing the appropriate methods. In this way, you can swap in any number of caching technologies into your Rails application. diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile index 7a3da134ac..58855bc80b 100644 --- a/railties/guides/source/command_line.textile +++ b/railties/guides/source/command_line.textile @@ -36,7 +36,7 @@ WARNING: You can install the rails gem by typing +gem install rails+, if you don <shell> $ rails new commandsapp create - create README + create README.rdoc create .gitignore create Rakefile create config.ru @@ -420,7 +420,7 @@ The +doc:+ namespace has the tools to generate documentation for your app, API d h4. +notes+ -+rake notes+ will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is only done in files with extension +.builder+, +.rb+ and +.erb+ for both default and custom annotations. ++rake notes+ will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is done in files with extension +.builder+, +.rb+, +.erb+, +.haml+ and +.slim+ for both default and custom annotations. <shell> $ rake notes @@ -509,8 +509,8 @@ $ rails new . --git --database=postgresql create tmp/pids create Rakefile add 'Rakefile' - create README -add 'README' + create README.rdoc +add 'README.rdoc' create app/controllers/application_controller.rb add 'app/controllers/application_controller.rb' create app/helpers/application_helper.rb diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 8e65dbccbb..f94d0ba4e5 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -82,6 +82,8 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is * +config.encoding+ sets up the application-wide encoding. Defaults to UTF-8. +* +config.file_watcher+ the class used to detect file updates in the filesystem when +config.reload_classes_only_on_change+ is true. Must conform to +ActiveSupport::FileUpdateChecker+ API. + * +config.filter_parameters+ used for filtering out the parameters that you don't want shown in the logs, such as passwords or credit card numbers. * +config.force_ssl+ forces all requests to be under HTTPS protocol by using +Rack::SSL+ middleware. @@ -98,6 +100,8 @@ NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is * +config.preload_frameworks+ enables or disables preloading all frameworks at startup. Enabled by +config.threadsafe!+. Defaults to +nil+, so is disabled. +* +config.reload_classes_only_on_change+ enables or disables reloading of classes only when tracked files change. By default tracks everything on autoload paths and is set to true. If +config.cache_classes+ is true, this option is ignored. + * +config.reload_plugins+ enables or disables plugin reloading. Defaults to false. * +config.secret_token+ used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get +config.secret_token+ initialized to a random key in +config/initializers/secret_token.rb+. diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index fe43c9db36..774c6a792e 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -289,7 +289,7 @@ rundown on the function of each of the files and folders that Rails created by d |log/|Application log files.| |public/|The only folder seen to the world as-is. Contains the static files and compiled assets.| |Rakefile|This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.| -|README|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.| +|README.rdoc|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.| |script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.| |test/|Unit tests, fixtures, and other test apparatus. These are covered in "Testing Rails Applications":testing.html| |tmp/|Temporary files| diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index f5f47acfbc..22689cc278 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/hash/reverse_merge' -require 'active_support/file_update_checker' require 'fileutils' require 'rails/plugin' require 'rails/engine' @@ -33,6 +32,25 @@ module Rails # # The Application is also responsible for building the middleware stack. # + # == Booting process + # + # The application is also responsible for setting up and executing the booting + # process. From the moment you require "config/application.rb" in your app, + # the booting process goes like this: + # + # 1) require "config/boot.rb" to setup load paths + # 2) require railties and engines + # 3) Define Rails.application as "class MyApp::Application < Rails::Application" + # 4) Run config.before_configuration callbacks + # 5) Load config/environments/ENV.rb + # 6) Run config.before_initialize callbacks + # 7) Run Railtie#initializer defined by railties, engines and application. + # One by one, each engine sets up its load paths, routes and runs its config/initializers/* files. + # 9) Custom Railtie#initializers added by railties, engines and applications are executed + # 10) Build the middleware stack and run to_prepare callbacks + # 11) Run config.before_eager_load and eager_load if cache classes is true + # 12) Run config.after_initialize callbacks + # class Application < Engine autoload :Bootstrap, 'rails/application/bootstrap' autoload :Configuration, 'rails/application/configuration' @@ -52,12 +70,14 @@ module Rails attr_accessor :assets, :sandbox alias_method :sandbox?, :sandbox + attr_reader :reloaders delegate :default_url_options, :default_url_options=, :to => :routes def initialize super @initialized = false + @reloaders = [] end # This method is called just after an application inherits from Rails::Application, @@ -83,27 +103,51 @@ module Rails require environment if environment end + # Reload application routes regardless if they changed or not. def reload_routes! routes_reloader.reload! end - def routes_reloader + def routes_reloader #:nodoc: @routes_reloader ||= RoutesReloader.new end - def initialize!(group=:default) + # Returns an array of file paths appended with a hash of directories-extensions + # suitable for ActiveSupport::FileUpdateChecker API. + def watchable_args + files = [] + files.concat config.watchable_files + + dirs = {} + dirs.merge! config.watchable_dirs + ActiveSupport::Dependencies.autoload_paths.each do |path| + dirs[path.to_s] = [:rb] + end + + [files, dirs] + end + + # Initialize the application passing the given group. By default, the + # group is :default but sprockets precompilation passes group equals + # to assets if initialize_on_precompile is false to avoid booting the + # whole app. + def initialize!(group=:default) #:nodoc: raise "Application has been already initialized." if @initialized run_initializers(group, self) @initialized = true self end + # Load the application and its railties tasks and invoke the registered hooks. + # Check <tt>Rails::Railtie.rake_tasks</tt> for more info. def load_tasks(app=self) initialize_tasks super self end + # Load the application console and invoke the registered hooks. + # Check <tt>Rails::Railtie.console</tt> for more info. def load_console(app=self) initialize_console super @@ -129,7 +173,8 @@ module Rails }) end - def ordered_railties + # Returns the ordered railties for this application considering railties_order. + def ordered_railties #:nodoc: @ordered_railties ||= begin order = config.railties_order.map do |railtie| if railtie == :main_app @@ -151,13 +196,13 @@ module Rails end end - def initializers + def initializers #:nodoc: Bootstrap.initializers_for(self) + super + Finisher.initializers_for(self) end - def config + def config #:nodoc: @config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd)) end @@ -165,7 +210,7 @@ module Rails self end - def helpers_paths + def helpers_paths #:nodoc: config.helpers_paths end @@ -173,6 +218,10 @@ module Rails alias :build_middleware_stack :app + def reload_dependencies? + config.reload_classes_only_on_change != true || reloaders.map(&:updated?).any? + end + def default_middleware_stack ActionDispatch::MiddlewareStack.new.tap do |middleware| if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache @@ -202,7 +251,11 @@ module Rails middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header end - middleware.use ::ActionDispatch::Reloader unless config.cache_classes + unless config.cache_classes + app = self + middleware.use ::ActionDispatch::Reloader, lambda { app.reload_dependencies? } + end + middleware.use ::ActionDispatch::Callbacks middleware.use ::ActionDispatch::Cookies @@ -222,7 +275,7 @@ module Rails end end - def initialize_tasks + def initialize_tasks #:nodoc: self.class.rake_tasks do require "rails/tasks" task :environment do @@ -232,7 +285,7 @@ module Rails end end - def initialize_console + def initialize_console #:nodoc: require "pp" require "rails/console/app" require "rails/console/helpers" diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb index c2cb121e42..e189009cc5 100644 --- a/railties/lib/rails/application/bootstrap.rb +++ b/railties/lib/rails/application/bootstrap.rb @@ -24,9 +24,18 @@ module Rails initializer :initialize_logger, :group => :all do Rails.logger ||= config.logger || begin path = config.paths["log"].first - logger = ActiveSupport::TaggedLogging.new(ActiveSupport::BufferedLogger.new(path)) + unless File.exist? File.dirname path + FileUtils.mkdir_p File.dirname path + end + + f = File.open path, 'w' + f.binmode + f.sync = !Rails.env.production? # make sure every write flushes + + logger = ActiveSupport::TaggedLogging.new( + ActiveSupport::BufferedLogger.new(f) + ) logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase) - logger.auto_flushing = false if Rails.env.production? logger rescue StandardError logger = ActiveSupport::TaggedLogging.new(ActiveSupport::BufferedLogger.new(STDERR)) @@ -37,7 +46,6 @@ module Rails ) logger end - at_exit { Rails.logger.flush if Rails.logger.respond_to?(:flush) } end # Initialize cache early in the stack so railties can make use of it. @@ -51,13 +59,6 @@ module Rails end end - initializer :set_clear_dependencies_hook, :group => :all do - ActionDispatch::Reloader.to_cleanup do - ActiveSupport::DescendantsTracker.clear - ActiveSupport::Dependencies.clear - end - end - # Sets the dependency loading mechanism. # TODO: Remove files from the $" and always use require. initializer :initialize_dependency_mechanism, :group => :all do diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index e95b0f5495..dddf7e498f 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/string/encoding' require 'active_support/core_ext/kernel/reporting' +require 'active_support/file_update_checker' require 'rails/engine/configuration' module Rails @@ -7,11 +8,11 @@ module Rails class Configuration < ::Rails::Engine::Configuration attr_accessor :allow_concurrency, :asset_host, :asset_path, :assets, :cache_classes, :cache_store, :consider_all_requests_local, - :dependency_loading, :filter_parameters, + :dependency_loading, :file_watcher, :filter_parameters, :force_ssl, :helpers_paths, :logger, :log_tags, :preload_frameworks, - :reload_plugins, :secret_token, :serve_static_assets, - :ssl_options, :static_cache_control, :session_options, - :time_zone, :whiny_nils, :railties_order + :railties_order, :relative_url_root, :reload_plugins, :secret_token, + :serve_static_assets, :ssl_options, :static_cache_control, :session_options, + :time_zone, :reload_classes_only_on_change, :whiny_nils attr_writer :log_level attr_reader :encoding @@ -19,23 +20,26 @@ module Rails def initialize(*) super self.encoding = "utf-8" - @allow_concurrency = false - @consider_all_requests_local = false - @filter_parameters = [] - @helpers_paths = [] - @dependency_loading = true - @serve_static_assets = true - @static_cache_control = nil - @force_ssl = false - @ssl_options = {} - @session_store = :cookie_store - @session_options = {} - @time_zone = "UTC" - @log_level = nil - @middleware = app_middleware - @generators = app_generators - @cache_store = [ :file_store, "#{root}/tmp/cache/" ] - @railties_order = [:all] + @allow_concurrency = false + @consider_all_requests_local = false + @filter_parameters = [] + @helpers_paths = [] + @dependency_loading = true + @serve_static_assets = true + @static_cache_control = nil + @force_ssl = false + @ssl_options = {} + @session_store = :cookie_store + @session_options = {} + @time_zone = "UTC" + @log_level = nil + @middleware = app_middleware + @generators = app_generators + @cache_store = [ :file_store, "#{root}/tmp/cache/" ] + @railties_order = [:all] + @relative_url_root = ENV["RAILS_RELATIVE_URL_ROOT"] + @reload_classes_only_on_change = true + @file_watcher = ActiveSupport::FileUpdateChecker @assets = ActiveSupport::OrderedOptions.new @assets.enabled = false diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index fc7d205a6f..2ce2980b97 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -20,12 +20,6 @@ module Rails end end - initializer :add_to_prepare_blocks do - config.to_prepare_blocks.each do |block| - ActionDispatch::Reloader.to_prepare(&block) - end - end - initializer :add_builtin_route do |app| if Rails.env.development? app.routes.append do @@ -38,14 +32,22 @@ module Rails build_middleware_stack end - initializer :run_prepare_callbacks do - ActionDispatch::Reloader.prepare! - end - initializer :define_main_app_helper do |app| app.routes.define_mounted_helper(:main_app) end + initializer :add_to_prepare_blocks do + config.to_prepare_blocks.each do |block| + ActionDispatch::Reloader.to_prepare(&block) + end + end + + # This needs to happen before eager load so it happens + # in exactly the same point regardless of config.cache_classes + initializer :run_prepare_callbacks do + ActionDispatch::Reloader.prepare! + end + initializer :eager_load! do if config.cache_classes && !$rails_rake_task ActiveSupport.run_load_hooks(:before_eager_load, self) @@ -53,17 +55,37 @@ module Rails end end + # All initialization is done, including eager loading in production initializer :finisher_hook do ActiveSupport.run_load_hooks(:after_initialize, self) end - # Force routes to be loaded just at the end and add it to to_prepare callbacks - # This needs to be after the finisher hook to ensure routes added in the hook - # are still loaded. - initializer :set_routes_reloader do |app| - reloader = lambda { app.routes_reloader.execute_if_updated } - reloader.call - ActionDispatch::Reloader.to_prepare(&reloader) + # Set app reload just after the finisher hook to ensure + # routes added in the hook are still loaded. + initializer :set_routes_reloader_hook do + reloader = routes_reloader + reloader.execute_if_updated + self.reloaders << reloader + ActionDispatch::Reloader.to_prepare { reloader.execute_if_updated } + end + + # Set app reload just after the finisher hook to ensure + # paths added in the hook are still loaded. + initializer :set_dependencies_hook, :group => :all do + callback = lambda do + ActiveSupport::DescendantsTracker.clear + ActiveSupport::Dependencies.clear + end + + if config.reload_classes_only_on_change + reloader = config.file_watcher.new(*watchable_args, &callback) + self.reloaders << reloader + # We need to set a to_prepare callback regardless of the reloader result, i.e. + # models should be reloaded if any of the reloaders (i18n, routes) were updated. + ActionDispatch::Reloader.to_prepare(:prepend => true){ reloader.execute } + else + ActionDispatch::Reloader.to_cleanup(&callback) + end end # Disable dependency loading during request cycle diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index 1d1f5e1b06..ef7e733ce4 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -1,10 +1,13 @@ +require "active_support/core_ext/module/delegation" + module Rails class Application - class RoutesReloader < ::ActiveSupport::FileUpdateChecker - attr_reader :route_sets + class RoutesReloader + attr_reader :route_sets, :paths + delegate :execute_if_updated, :execute, :updated?, :to => :updater def initialize - super([]) { reload! } + @paths = [] @route_sets = [] end @@ -16,7 +19,15 @@ module Rails revert end - protected + private + + def updater + @updater ||= begin + updater = ActiveSupport::FileUpdateChecker.new(paths) { reload! } + updater.execute + updater + end + end def clear! route_sets.each do |routes| diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index f424492bb4..d6015e9c01 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -30,7 +30,7 @@ module Rails # # config.generators.colorize_logging = false # - def generators #:nodoc + def generators #:nodoc: @generators ||= Rails::Configuration::Generators.new yield(@generators) if block_given? @generators diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 3fbde0d989..0bd39cb2cd 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -193,7 +193,8 @@ module Rails end def assets_gemfile_entry - <<-GEMFILE.strip_heredoc + return if options[:skip_sprockets] + <<-GEMFILE.strip_heredoc.gsub(/^[ \t]*$/, '') # Gems used only for assets and not required # in production environments by default. group :assets do diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 3e32f758a4..2a6bd57df4 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -38,7 +38,7 @@ module Rails end def readme - copy_file "README" + copy_file "README", "README.rdoc" end def gemfile diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index d3b8f4d595..c260cc999b 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,4 +1,4 @@ -source 'http://rubygems.org' +source 'https://rubygems.org' <%= rails_gemfile_entry -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 40fd843b1b..c6dfa1f2dd 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -54,6 +54,12 @@ module <%= app_const_base %> # like if you have constraints or database-specific column types # config.active_record.schema_format = :sql + # Enforce whitelist mode for mass assignment. + # This will create an empty whitelist of attributes available for mass-assignment for all models + # in your app. As such, your models will need to explicitly whitelist or blacklist accessible + # parameters by using an attr_accessible or attr_protected declaration. + # config.active_record.whitelist_attributes = true + <% unless options.skip_sprockets? -%> # Enable the asset pipeline config.assets.enabled = true diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index beaf941282..9e53b6a70d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -31,9 +31,11 @@ config.active_record.auto_explain_threshold_in_seconds = 0.5 <%- end -%> + <%- unless options.skip_sprockets? -%> # Do not compress assets config.assets.compress = false # Expands the lines which load the assets config.assets.debug = true + <%- end -%> end diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 40ec3fc644..0f571f7c1a 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -11,6 +11,7 @@ # Disable Rails's static asset server (Apache or nginx will already do this) config.serve_static_assets = false + <%- unless options.skip_sprockets? -%> # Compress JavaScripts and CSS config.assets.compress = true @@ -22,6 +23,7 @@ # Defaults to Rails.root.join("public/assets") # config.assets.manifest = YOUR_PATH + <%- end -%> # Specifies the header that your server uses for sending files # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache @@ -45,8 +47,10 @@ # Enable serving of images, stylesheets, and JavaScripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" + <%- unless options.skip_sprockets? -%> # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) # config.assets.precompile += %w( search.js ) + <%- end -%> # Disable delivery errors, bad email addresses will be ignored # config.action_mailer.raise_delivery_errors = false diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index f888684117..cf9e4ad500 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -7,6 +7,18 @@ module Rails @@options ||= {} end + # Add files that should be watched for change. + def watchable_files + @@watchable_files ||= [] + end + + # Add directories that should be watched for change. + # The key of the hashes should be directories and the values should + # be an array of extensions to match in each directory. + def watchable_dirs + @@watchable_dirs ||= {} + end + # This allows you to modify the application's middlewares from Engines. # # All operations you run on the app_middleware will be replayed on the diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index a9f2180196..2286e0477a 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -46,16 +46,14 @@ class SourceAnnotationExtractor end # Returns a hash that maps filenames under +dirs+ (recursively) to arrays - # with their annotations. Only files with annotations are included, and only - # those with extension +.builder+, +.rb+, and +.erb+ - # are taken into account. + # with their annotations. def find(dirs=%w(app config lib script test)) dirs.inject({}) { |h, dir| h.update(find_in(dir)) } end # Returns a hash that maps filenames under +dir+ (recursively) to arrays # with their annotations. Only files with annotations are included, and only - # those with extension +.builder+, +.rb+, and +.erb+ + # those with extension +.builder+, +.rb+, +.erb+, +.haml+ and +.slim+ # are taken into account. def find_in(dir) results = {} @@ -69,6 +67,10 @@ class SourceAnnotationExtractor results.update(extract_annotations_from(item, /#\s*(#{tag}):?\s*(.*)$/)) elsif item =~ /\.erb$/ results.update(extract_annotations_from(item, /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/)) + elsif item =~ /\.haml$/ + results.update(extract_annotations_from(item, /-\s*#\s*(#{tag}):?\s*(.*)$/)) + elsif item =~ /\.slim$/ + results.update(extract_annotations_from(item, /\/\s*\s*(#{tag}):?\s*(.*)$/)) end end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index a22013f81c..a08ea77ff3 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -72,7 +72,7 @@ module ApplicationTests end end - test "precompile application.js and application.css and all other files not ending with .js or .css by default" do + test "precompile application.js and application.css and all other non JS/CSS files" do app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/stylesheets/application.css", "body{}" @@ -82,8 +82,11 @@ module ApplicationTests app_file "app/assets/javascripts/something.min.js", "alert();" app_file "app/assets/stylesheets/something.min.css", "body{}" + app_file "app/assets/javascripts/something.else.js.erb", "alert();" + app_file "app/assets/stylesheets/something.else.css.erb", "body{}" + images_should_compile = ["a.png", "happyface.png", "happy_face.png", "happy.face.png", - "happy-face.png", "happy.happy_face.png", "happy_happy.face.png", + "happy-face.png", "happy.happy_face.png", "happy_happy.face.png", "happy.happy.face.png", "happy", "happy.face", "-happyface", "-happy.png", "-happy.face.png", "_happyface", "_happy.face.png", "_happy.png"] @@ -106,6 +109,9 @@ module ApplicationTests assert !File.exists?("#{app_path}/public/assets/something.min.js") assert !File.exists?("#{app_path}/public/assets/something.min.css") + + assert !File.exists?("#{app_path}/public/assets/something.else.js") + assert !File.exists?("#{app_path}/public/assets/something.else.css") end test "asset pipeline should use a Sprockets::Index when config.assets.digest is true" do @@ -472,6 +478,15 @@ module ApplicationTests assert_match 'src="//example.com/assets/rails.png"', File.read("#{app_path}/public/assets/image_loader.js") end + test "asset paths should use RAILS_RELATIVE_URL_ROOT by default" do + ENV["RAILS_RELATIVE_URL_ROOT"] = "/sub/uri" + + app_file "app/assets/javascripts/app.js.erb", 'var src="<%= image_path("rails.png") %>";' + add_to_config "config.assets.precompile = %w{app.js}" + precompile! + + assert_match 'src="/sub/uri/assets/rails.png"', File.read("#{app_path}/public/assets/app.js") + end private diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index 2073c780bf..6f9d8d57b1 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -61,7 +61,8 @@ class ConsoleTest < Test::Unit::TestCase load_environment assert User.new.respond_to?(:name) - assert !User.new.respond_to?(:age) + + sleep(1) app_file "app/models/user.rb", <<-MODEL class User diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index 446c85d65a..cf6c4d8fc2 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -136,6 +136,13 @@ module ApplicationTests assert_equal 2, ActionDispatch::Http::URL.tld_length end + test "assignment config.encoding to default_charset" do + charset = "ruby".respond_to?(:force_encoding) ? 'Shift_JIS' : 'UTF8' + add_to_config "config.encoding = '#{charset}'" + require "#{app_path}/config/environment" + assert_equal charset, ActionDispatch::Response.default_charset + end + # AS test "if there's no config.active_support.bare, all of ActiveSupport is required" do use_frameworks [] diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index 47c6fd5c6e..9c77f6210a 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -16,7 +16,7 @@ class LoadingTest < Test::Unit::TestCase @app ||= Rails.application end - def test_constants_in_app_are_autoloaded + test "constants in app are autoloaded" do app_file "app/models/post.rb", <<-MODEL class Post < ActiveRecord::Base validates_acceptance_of :title, :accept => "omg" @@ -33,7 +33,7 @@ class LoadingTest < Test::Unit::TestCase assert_equal 'omg', p.title end - def test_models_without_table_do_not_panic_on_scope_definitions_when_loaded + test "models without table do not panic on scope definitions when loaded" do app_file "app/models/user.rb", <<-MODEL class User < ActiveRecord::Base default_scope where(:published => true) @@ -63,9 +63,10 @@ class LoadingTest < Test::Unit::TestCase assert ::AppTemplate::Application.config.loaded end - def test_descendants_are_cleaned_on_each_request_without_cache_classes + test "descendants are cleaned on each request without cache classes" do add_to_config <<-RUBY config.cache_classes = false + config.reload_classes_only_on_change = false RUBY app_file "app/models/post.rb", <<-MODEL @@ -98,6 +99,114 @@ class LoadingTest < Test::Unit::TestCase assert_raise(RuntimeError) { ::AppTemplate::Application.initialize! } end + test "reload constants on development" do + add_to_config <<-RUBY + config.cache_classes = false + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match '/c', :to => lambda { |env| [200, {"Content-Type" => "text/plain"}, [User.counter.to_s]] } + end + RUBY + + app_file "app/models/user.rb", <<-MODEL + class User + def self.counter; 1; end + end + MODEL + + require 'rack/test' + extend Rack::Test::Methods + + require "#{rails_root}/config/environment" + sleep(1) + + get "/c" + assert_equal "1", last_response.body + + app_file "app/models/user.rb", <<-MODEL + class User + def self.counter; 2; end + end + MODEL + + get "/c" + assert_equal "2", last_response.body + end + + test "does not reload constants on development if custom file watcher always returns false" do + add_to_config <<-RUBY + config.cache_classes = false + config.file_watcher = Class.new do + def initialize(*); end + def updated?; false; end + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match '/c', :to => lambda { |env| [200, {"Content-Type" => "text/plain"}, [User.counter.to_s]] } + end + RUBY + + app_file "app/models/user.rb", <<-MODEL + class User + def self.counter; 1; end + end + MODEL + + require 'rack/test' + extend Rack::Test::Methods + + require "#{rails_root}/config/environment" + sleep(1) + + get "/c" + assert_equal "1", last_response.body + + app_file "app/models/user.rb", <<-MODEL + class User + def self.counter; 2; end + end + MODEL + + get "/c" + assert_equal "1", last_response.body + end + + test "added files also trigger reloading" do + add_to_config <<-RUBY + config.cache_classes = false + RUBY + + app_file 'config/routes.rb', <<-RUBY + $counter = 0 + AppTemplate::Application.routes.draw do + match '/c', :to => lambda { |env| User; [200, {"Content-Type" => "text/plain"}, [$counter.to_s]] } + end + RUBY + + app_file "app/models/user.rb", <<-MODEL + class User + $counter += 1 + end + MODEL + + require 'rack/test' + extend Rack::Test::Methods + + require "#{rails_root}/config/environment" + + get "/c" + assert_equal "1", last_response.body + + app_file "db/schema.rb", "" + + get "/c" + assert_equal "2", last_response.body + end + protected def setup_ar! diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb index 050a2161ae..790c5b2d53 100644 --- a/railties/test/application/middleware/cache_test.rb +++ b/railties/test/application/middleware/cache_test.rb @@ -54,9 +54,9 @@ module ApplicationTests def test_cache_keeps_if_modified_since simple_controller expected = "Wed, 30 May 1984 19:43:31 GMT" - + get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected - + assert_equal 200, last_response.status assert_equal expected, last_response.body, "cache should have kept If-Modified-Since" end diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb new file mode 100644 index 0000000000..fd8a30557e --- /dev/null +++ b/railties/test/application/rake/migrations_test.rb @@ -0,0 +1,109 @@ +require "isolation/abstract_unit" + +module ApplicationTests + module RakeTests + class RakeMigrationsTest < Test::Unit::TestCase + def setup + build_app + boot_rails + FileUtils.rm_rf("#{app_path}/config/environments") + end + + def teardown + teardown_app + end + + test 'running migrations with given scope' do + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + end + app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION + class AMigration < ActiveRecord::Migration + end + MIGRATION + + output = Dir.chdir(app_path) { `rake db:migrate SCOPE=bukkits` } + assert_no_match(/create_table\(:users\)/, output) + assert_no_match(/CreateUsers/, output) + assert_no_match(/add_column\(:users, :email, :string\)/, output) + + assert_match(/AMigration: migrated/, output) + + output = Dir.chdir(app_path) { `rake db:migrate SCOPE=bukkits VERSION=0` } + assert_no_match(/drop_table\(:users\)/, output) + assert_no_match(/CreateUsers/, output) + assert_no_match(/remove_column\(:users, :email\)/, output) + + assert_match(/AMigration: reverted/, output) + end + + test 'model and migration generator with change syntax' do + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + `rails generate migration add_email_to_users email:string` + end + + output = Dir.chdir(app_path){ `rake db:migrate` } + assert_match(/create_table\(:users\)/, output) + assert_match(/CreateUsers: migrated/, output) + assert_match(/add_column\(:users, :email, :string\)/, output) + assert_match(/AddEmailToUsers: migrated/, output) + + output = Dir.chdir(app_path){ `rake db:rollback STEP=2` } + assert_match(/drop_table\("users"\)/, output) + assert_match(/CreateUsers: reverted/, output) + assert_match(/remove_column\("users", :email\)/, output) + assert_match(/AddEmailToUsers: reverted/, output) + end + + test 'migration status when schema migrations table is not present' do + output = Dir.chdir(app_path){ `rake db:migrate:status` } + assert_equal "Schema migrations table does not exist yet.\n", output + end + + test 'test migration status' do + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + `rails generate migration add_email_to_users email:string` + end + + Dir.chdir(app_path) { `rake db:migrate`} + output = Dir.chdir(app_path) { `rake db:migrate:status` } + + assert_match(/up\s+\d{14}\s+Create users/, output) + assert_match(/up\s+\d{14}\s+Add email to users/, output) + + Dir.chdir(app_path) { `rake db:rollback STEP=1` } + output = Dir.chdir(app_path) { `rake db:migrate:status` } + + assert_match(/up\s+\d{14}\s+Create users/, output) + assert_match(/down\s+\d{14}\s+Add email to users/, output) + end + + test 'test migration status after rollback and redo' do + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + `rails generate migration add_email_to_users email:string` + end + + Dir.chdir(app_path) { `rake db:migrate`} + output = Dir.chdir(app_path) { `rake db:migrate:status` } + + assert_match(/up\s+\d{14}\s+Create users/, output) + assert_match(/up\s+\d{14}\s+Add email to users/, output) + + Dir.chdir(app_path) { `rake db:rollback STEP=2` } + output = Dir.chdir(app_path) { `rake db:migrate:status` } + + assert_match(/down\s+\d{14}\s+Create users/, output) + assert_match(/down\s+\d{14}\s+Add email to users/, output) + + Dir.chdir(app_path) { `rake db:migrate:redo` } + output = Dir.chdir(app_path) { `rake db:migrate:status` } + + assert_match(/up\s+\d{14}\s+Create users/, output) + assert_match(/up\s+\d{14}\s+Add email to users/, output) + end + end + end +end diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb new file mode 100644 index 0000000000..659cbfec0f --- /dev/null +++ b/railties/test/application/rake/notes_test.rb @@ -0,0 +1,45 @@ +require "isolation/abstract_unit" + +module ApplicationTests + module RakeTests + class RakeNotesTest < Test::Unit::TestCase + def setup + build_app + require "rails/all" + end + + def teardown + teardown_app + end + + test 'notes' do + + app_file "app/views/home/index.html.erb", "<% # TODO: note in erb %>" + app_file "app/views/home/index.html.haml", "-# TODO: note in haml" + app_file "app/views/home/index.html.slim", "/ TODO: note in slim" + + boot_rails + require 'rake' + require 'rdoc/task' + require 'rake/testtask' + + Rails.application.load_tasks + + Dir.chdir(app_path) do + output = `bundle exec rake notes` + + assert_match /note in erb/, output + assert_match /note in haml/, output + assert_match /note in slim/, output + end + + end + + private + def boot_rails + super + require "#{app_path}/config/environment" + end + end + end +end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index c76bc3d526..4e406f23d2 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -108,74 +108,6 @@ module ApplicationTests assert_match "Sample log message", output end - def test_model_and_migration_generator_with_change_syntax - Dir.chdir(app_path) do - `rails generate model user username:string password:string` - `rails generate migration add_email_to_users email:string` - end - - output = Dir.chdir(app_path){ `rake db:migrate` } - assert_match(/create_table\(:users\)/, output) - assert_match(/CreateUsers: migrated/, output) - assert_match(/add_column\(:users, :email, :string\)/, output) - assert_match(/AddEmailToUsers: migrated/, output) - - output = Dir.chdir(app_path){ `rake db:rollback STEP=2` } - assert_match(/drop_table\("users"\)/, output) - assert_match(/CreateUsers: reverted/, output) - assert_match(/remove_column\("users", :email\)/, output) - assert_match(/AddEmailToUsers: reverted/, output) - end - - def test_migration_status_when_schema_migrations_table_is_not_present - output = Dir.chdir(app_path){ `rake db:migrate:status` } - assert_equal "Schema migrations table does not exist yet.\n", output - end - - def test_migration_status - Dir.chdir(app_path) do - `rails generate model user username:string password:string` - `rails generate migration add_email_to_users email:string` - end - - Dir.chdir(app_path) { `rake db:migrate`} - output = Dir.chdir(app_path) { `rake db:migrate:status` } - - assert_match(/up\s+\d{14}\s+Create users/, output) - assert_match(/up\s+\d{14}\s+Add email to users/, output) - - Dir.chdir(app_path) { `rake db:rollback STEP=1` } - output = Dir.chdir(app_path) { `rake db:migrate:status` } - - assert_match(/up\s+\d{14}\s+Create users/, output) - assert_match(/down\s+\d{14}\s+Add email to users/, output) - end - - def test_migration_status_after_rollback_and_redo - Dir.chdir(app_path) do - `rails generate model user username:string password:string` - `rails generate migration add_email_to_users email:string` - end - - Dir.chdir(app_path) { `rake db:migrate`} - output = Dir.chdir(app_path) { `rake db:migrate:status` } - - assert_match(/up\s+\d{14}\s+Create users/, output) - assert_match(/up\s+\d{14}\s+Add email to users/, output) - - Dir.chdir(app_path) { `rake db:rollback STEP=2` } - output = Dir.chdir(app_path) { `rake db:migrate:status` } - - assert_match(/down\s+\d{14}\s+Create users/, output) - assert_match(/down\s+\d{14}\s+Add email to users/, output) - - Dir.chdir(app_path) { `rake db:migrate:redo` } - output = Dir.chdir(app_path) { `rake db:migrate:status` } - - assert_match(/up\s+\d{14}\s+Create users/, output) - assert_match(/up\s+\d{14}\s+Add email to users/, output) - end - def test_loading_specific_fixtures Dir.chdir(app_path) do `rails generate model user username:string password:string` diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index c1fd6a38f1..ee288871de 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -114,7 +114,7 @@ class ActionsTest < Rails::Generators::TestCase action :gem_group, :test do gem 'fakeweb' end - + assert_file 'Gemfile', /\ngroup :development, :test do\n gem "rspec-rails"\nend\n\ngroup :test do\n gem "fakeweb"\nend/ end @@ -233,14 +233,14 @@ class ActionsTest < Rails::Generators::TestCase def test_readme run_generator Rails::Generators::AppGenerator.expects(:source_root).times(2).returns(destination_root) - assert_match(/Welcome to Rails/, action(:readme, "README")) + assert_match(/Welcome to Rails/, action(:readme, "README.rdoc")) end def test_readme_with_quiet generator(default_arguments, :quiet => true) run_generator Rails::Generators::AppGenerator.expects(:source_root).times(2).returns(destination_root) - assert_no_match(/Welcome to Rails/, action(:readme, "README")) + assert_no_match(/Welcome to Rails/, action(:readme, "README.rdoc")) end def test_log diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index baa80419a6..30fbe74e83 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -124,6 +124,16 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "hats/config/environment.rb", /Hats::Application\.initialize!/ end + def test_gemfile_has_no_whitespace_errors + run_generator + absolute = File.expand_path("Gemfile", destination_root) + File.open(absolute, 'r') do |f| + f.each_line do |line| + assert_no_match /^[ \t]+$/, line + end + end + end + def test_config_database_is_added_by_default run_generator assert_file "config/database.yml", /sqlite3/ @@ -206,13 +216,29 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content) assert_no_match(/config\.assets\.enabled = true/, content) end + assert_file "Gemfile" do |content| + assert_no_match(/sass-rails/, content) + assert_no_match(/coffee-rails/, content) + assert_no_match(/uglifier/, content) + end + assert_file "config/environments/development.rb" do |content| + assert_no_match(/config\.assets\.debug = true/, content) + end + assert_file "config/environments/production.rb" do |content| + assert_no_match(/config\.assets\.digest = true/, content) + assert_no_match(/config\.assets\.compress = true/, content) + end assert_file "test/performance/browsing_test.rb" end def test_inclusion_of_therubyrhino_under_jruby + run_generator([destination_root]) if defined?(JRUBY_VERSION) - run_generator([destination_root]) assert_file "Gemfile", /gem\s+["']therubyrhino["']$/ + else + assert_file "Gemfile" do |content| + assert_no_match(/gem\s+["']therubyrhino["']$/, content) + end end end diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index 7653e52d26..a15dae2a0a 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -56,6 +56,8 @@ module RailtiesTest app_file "db/migrate/1_create_sessions.rb", <<-RUBY class CreateSessions < ActiveRecord::Migration + def up + end end RUBY @@ -76,19 +78,19 @@ module RailtiesTest Dir.chdir(app_path) do output = `bundle exec rake bukkits:install:migrations` - assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") - assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb") - assert_match(/Copied migration 2_create_users.rb from bukkits/, output) - assert_match(/Copied migration 3_add_last_name_to_users.rb from bukkits/, output) + assert File.exists?("#{app_path}/db/migrate/2_create_users.bukkits.rb") + assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb") + assert_match(/Copied migration 2_create_users.bukkits.rb from bukkits/, output) + assert_match(/Copied migration 3_add_last_name_to_users.bukkits.rb from bukkits/, output) assert_match(/NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/, output) assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length output = `bundle exec rake railties:install:migrations`.split("\n") - assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.rb") + assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.acts_as_yaffle.rb") assert_no_match(/2_create_users/, output.join("\n")) - yaffle_migration_order = output.index(output.detect{|o| /Copied migration 4_create_yaffles.rb from acts_as_yaffle/ =~ o }) + yaffle_migration_order = output.index(output.detect{|o| /Copied migration 4_create_yaffles.acts_as_yaffle.rb from acts_as_yaffle/ =~ o }) bukkits_migration_order = output.index(output.detect{|o| /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/ =~ o }) assert_not_nil yaffle_migration_order, "Expected migration to be copied" assert_not_nil bukkits_migration_order, "Expected migration to be skipped" |