From bffaa888ac4a1ee60a9f93650b9184a9402eff09 Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 08:28:53 -0400 Subject: Custom serializers and deserializers in MessageVerifier and MessageEncryptor. By default, these classes use Marshal for serializing and deserializing messages. Unfortunately, the Marshal format is closely associated with Ruby internals and even changes between different interpreters. This makes the resulting message very hard to impossible to unserialize messages generated by these classes in other environments like node.js. This patch solves this by allowing you to set your own custom serializer and deserializer lambda functions. By default, it still uses Marshal to be backwards compatible. --- activesupport/lib/active_support/message_encryptor.rb | 8 ++++++-- activesupport/lib/active_support/message_verifier.rb | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 4f7cd12d48..05d6790075 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,9 +13,13 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError + attr_accessor :serializer, :deserializer + def initialize(secret, cipher = 'aes-256-cbc') @secret = secret @cipher = cipher + @serializer = lambda { |value| Marshal.dump(value) } + @deserializer = lambda { |value| Marshal.load(value) } end def encrypt(value) @@ -27,7 +31,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(Marshal.dump(value)) + encrypted_data = cipher.update(serializer.call(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -44,7 +48,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - Marshal.load(decrypted_data) + deserializer.call(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 8f3946325a..e38e242cfe 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -21,9 +21,13 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end + attr_accessor :serializer, :deserializer + def initialize(secret, digest = 'SHA1') @secret = secret @digest = digest + @serializer = lambda { |value| Marshal.dump(value) } + @deserializer = lambda { |value| Marshal.load(value) } end def verify(signed_message) @@ -31,14 +35,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - Marshal.load(ActiveSupport::Base64.decode64(data)) + deserializer.call(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(Marshal.dump(value)) + data = ActiveSupport::Base64.encode64s(serializer.call(value)) "#{data}--#{generate_digest(data)}" end -- cgit v1.2.3 From db040cdf8ba832123bae68764189bbcb569d473a Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 13:15:21 -0400 Subject: Implement API suggestions of pull request. --- activesupport/lib/active_support/message_encryptor.rb | 11 +++++------ activesupport/lib/active_support/message_verifier.rb | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 05d6790075..66e121be26 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,13 +13,12 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError - attr_accessor :serializer, :deserializer + attr_accessor :serializer - def initialize(secret, cipher = 'aes-256-cbc') + def initialize(secret, cipher = 'aes-256-cbc', serializer = Marshal) @secret = secret @cipher = cipher - @serializer = lambda { |value| Marshal.dump(value) } - @deserializer = lambda { |value| Marshal.load(value) } + @serializer = serializer end def encrypt(value) @@ -31,7 +30,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(serializer.call(value)) + encrypted_data = cipher.update(serializer.dump(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -48,7 +47,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - deserializer.call(decrypted_data) + serializer.load(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index e38e242cfe..b3a087a596 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -21,13 +21,12 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end - attr_accessor :serializer, :deserializer + attr_accessor :serializer - def initialize(secret, digest = 'SHA1') + def initialize(secret, digest = 'SHA1', serializer = Marshal) @secret = secret @digest = digest - @serializer = lambda { |value| Marshal.dump(value) } - @deserializer = lambda { |value| Marshal.load(value) } + @serializer = serializer end def verify(signed_message) @@ -35,14 +34,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - deserializer.call(ActiveSupport::Base64.decode64(data)) + serializer.load(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(serializer.call(value)) + data = ActiveSupport::Base64.encode64s(serializer.dump(value)) "#{data}--#{generate_digest(data)}" end -- cgit v1.2.3 From 2d30d4cb888e2da7c1f0a8828b467d2e21c90cfa Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 13:23:08 -0400 Subject: Add some documentation for the new serializer property of MessageVerifier and MessageEncryptor. --- activesupport/lib/active_support/message_verifier.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index b3a087a596..0181070479 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -18,6 +18,11 @@ module ActiveSupport # self.current_user = User.find(id) # end # + # By default it uses Marshal to serialize the message. If you want to use another + # serialization method, you can set the serializer attribute to something that responds + # to dump and load, e.g.: + # + # @verifier.serializer = YAML class MessageVerifier class InvalidSignature < StandardError; end -- cgit v1.2.3 From 41fea0334232824d5d509a6924e8c8487d53494b Mon Sep 17 00:00:00 2001 From: Willem van Bergen Date: Thu, 15 Sep 2011 14:27:12 -0400 Subject: Use an options hash to specify digest/cipher algorithm and a serializer for MessageVerifier and MessageEncryptor. --- activesupport/lib/active_support/message_encryptor.rb | 17 ++++++++++------- activesupport/lib/active_support/message_verifier.rb | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 66e121be26..7637cfe2b0 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,12 +13,15 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError - attr_accessor :serializer - - def initialize(secret, cipher = 'aes-256-cbc', serializer = Marshal) + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to sepcify the cipher algorithm." + options = { :cipher => options } + end + @secret = secret - @cipher = cipher - @serializer = serializer + @cipher = options[:cipher] || 'aes-256-cbc' + @serializer = options[:serializer] || Marshal end def encrypt(value) @@ -30,7 +33,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(serializer.dump(value)) + encrypted_data = cipher.update(@serializer.dump(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -47,7 +50,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - serializer.load(decrypted_data) + @serializer.load(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 0181070479..57317028fc 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -26,12 +26,15 @@ module ActiveSupport class MessageVerifier class InvalidSignature < StandardError; end - attr_accessor :serializer - - def initialize(secret, digest = 'SHA1', serializer = Marshal) + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to sepcify the digest algorithm." + options = { :digest => options } + end + @secret = secret - @digest = digest - @serializer = serializer + @digest = options[:digest] || 'SHA1' + @serializer = options[:serializer] || Marshal end def verify(signed_message) @@ -39,14 +42,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - serializer.load(ActiveSupport::Base64.decode64(data)) + @serializer.load(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(serializer.dump(value)) + data = ActiveSupport::Base64.encode64s(@serializer.dump(value)) "#{data}--#{generate_digest(data)}" end -- cgit v1.2.3 From c9aac2a215d46d25556a6a0eaae1b9f85231a6b4 Mon Sep 17 00:00:00 2001 From: Peter Suschlik Date: Fri, 16 Sep 2011 09:08:53 +0300 Subject: Fix typo in deprecation warning. --- activesupport/lib/active_support/message_encryptor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 7637cfe2b0..e14386a85d 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -15,7 +15,7 @@ module ActiveSupport def initialize(secret, options = {}) unless options.is_a?(Hash) - ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to sepcify the cipher algorithm." + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to specify the cipher algorithm." options = { :cipher => options } end -- cgit v1.2.3 From b0ae34ad72ed8410e6f16c1d9ee4b04b2630208f Mon Sep 17 00:00:00 2001 From: Claudio Poli Date: Fri, 16 Sep 2011 19:54:48 +0300 Subject: Fix typo in deprecation notice --- activesupport/lib/active_support/message_verifier.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 57317028fc..9d7c81142a 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -28,7 +28,7 @@ module ActiveSupport def initialize(secret, options = {}) unless options.is_a?(Hash) - ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to sepcify the digest algorithm." + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to specify the digest algorithm." options = { :digest => options } end -- cgit v1.2.3 From 3a04e370e4cc016bb7b59fe6bb704e4ca37d62f3 Mon Sep 17 00:00:00 2001 From: brainopia Date: Fri, 16 Sep 2011 22:59:16 +0400 Subject: Fix Hash#to_query edge case with html_safe string on 1.8 ruby --- activesupport/lib/active_support/core_ext/object/to_query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb index 3f1540f685..5d5fcf00e0 100644 --- a/activesupport/lib/active_support/core_ext/object/to_query.rb +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -7,7 +7,7 @@ class Object # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work. def to_query(key) require 'cgi' unless defined?(CGI) && defined?(CGI::escape) - "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" + "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}" end end -- cgit v1.2.3 From 18116791d00d693643db3b4a99ae1d245c5a6c33 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 16 Sep 2011 17:25:40 -0700 Subject: Proper lines numbers for stack trace info --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') 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 05b39b89bf..3ae3d64fa4 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -142,7 +142,7 @@ module ActiveSupport #:nodoc: end UNSAFE_STRING_METHODS.each do |unsafe_method| - class_eval <<-EOT, __FILE__, __LINE__ + class_eval <<-EOT, __FILE__, __LINE__ + 1 def #{unsafe_method}(*args, &block) # def capitalize(*args, &block) to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block) end # end -- cgit v1.2.3 From 8aa537c9452d40aeaf25e6d7e0c5bb1205b05d1a Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Thu, 22 Sep 2011 02:13:04 +0530 Subject: fix incorrect comment --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') 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 3ae3d64fa4..94999807dd 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -144,7 +144,7 @@ module ActiveSupport #:nodoc: UNSAFE_STRING_METHODS.each do |unsafe_method| class_eval <<-EOT, __FILE__, __LINE__ + 1 def #{unsafe_method}(*args, &block) # def capitalize(*args, &block) - to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block) + to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block) end # end def #{unsafe_method}!(*args) # def capitalize!(*args) -- cgit v1.2.3 From 8d63678d1406c5518d437709af0fde717c0248d7 Mon Sep 17 00:00:00 2001 From: Philippe Huibonhoa Date: Wed, 21 Sep 2011 21:00:46 -0700 Subject: Fixed issue in file store where it could create a filename that was too long for the file system. (https://github.com/rails/rails/issues/3072) --- activesupport/lib/active_support/cache/file_store.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index f7c01948b4..ab2382d98c 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -13,6 +13,7 @@ module ActiveSupport attr_reader :cache_path DIR_FORMATTER = "%03X" + FILENAME_MAX_SIZE = 230 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) def initialize(cache_path, options = nil) super(options) @@ -129,15 +130,13 @@ module ActiveSupport hash, dir_1 = hash.divmod(0x1000) dir_2 = hash.modulo(0x1000) fname_paths = [] - # Make sure file name is < 255 characters so it doesn't exceed file system limits. - if fname.size <= 255 - fname_paths << fname - else - while fname.size <= 255 - fname_path << fname[0, 255] - fname = fname[255, -1] - end - end + + # Make sure file name doesn't exceed file system limits. + begin + fname_paths << fname[0...FILENAME_MAX_SIZE] + fname = fname[FILENAME_MAX_SIZE..-1] + end until fname.blank? + File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths) end -- cgit v1.2.3 From 667ef57de641f4915f50d93f35756892151ee34b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 22 Sep 2011 14:14:24 -0300 Subject: No need to create a range object --- activesupport/lib/active_support/cache/file_store.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index ab2382d98c..3f516d4808 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -130,13 +130,13 @@ module ActiveSupport hash, dir_1 = hash.divmod(0x1000) dir_2 = hash.modulo(0x1000) fname_paths = [] - + # Make sure file name doesn't exceed file system limits. begin - fname_paths << fname[0...FILENAME_MAX_SIZE] + fname_paths << fname[0, FILENAME_MAX_SIZE] fname = fname[FILENAME_MAX_SIZE..-1] end until fname.blank? - + File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths) end -- cgit v1.2.3 From 310565f537b5eeb134e9a4bb0801358432f03e04 Mon Sep 17 00:00:00 2001 From: Ryan Oblak Date: Thu, 22 Sep 2011 12:17:42 -0700 Subject: Added ActiveSupport::Inflector.safe_constantize and String#safe_constantize; refactored common constantize tests into ConstantizeTestCases --- .../active_support/core_ext/string/inflections.rb | 19 ++++++++++++--- .../lib/active_support/inflector/methods.rb | 27 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index 002688d6c0..b4218cb42c 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -33,14 +33,27 @@ class String # +constantize+ tries to find a declared constant with the name specified # in the string. It raises a NameError when the name is not in CamelCase - # or is not initialized. + # or is not initialized. See ActiveSupport::Inflector.constantize # # Examples - # "Module".constantize # => Module - # "Class".constantize # => Class + # "Module".constantize # => Module + # "Class".constantize # => Class + # "blargle".safe_constantize # => NameError: wrong constant name blargle def constantize ActiveSupport::Inflector.constantize(self) end + + # +safe_constantize+ tries to find a declared constant with the name specified + # in the string. It returns nil when the name is not in CamelCase + # or is not initialized. See ActiveSupport::Inflector.safe_constantize + # + # Examples + # "Module".safe_constantize # => Module + # "Class".safe_constantize # => Class + # "blargle".safe_constantize # => nil + def safe_constantize + ActiveSupport::Inflector.safe_constantize(self) + end # By default, +camelize+ converts strings to UpperCamelCase. If the argument to camelize # is set to :lower then camelize produces lowerCamelCase. diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 423b5abd20..b22e39c7c2 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -224,6 +224,33 @@ module ActiveSupport end end + # Tries to find a constant with the name specified in the argument string: + # + # "Module".safe_constantize # => Module + # "Test::Unit".safe_constantize # => Test::Unit + # + # The name is assumed to be the one of a top-level constant, no matter whether + # it starts with "::" or not. No lexical context is taken into account: + # + # C = 'outside' + # module M + # C = 'inside' + # C # => 'inside' + # "C".safe_constantize # => 'outside', same as ::C + # end + # + # nil is returned when the name is not in CamelCase or the constant is + # unknown. + # + # "blargle".safe_constantize # => nil + def safe_constantize(camel_cased_word) + begin + camel_cased_word.constantize + rescue NameError + nil + end + end + # Turns a number into an ordinal string used to denote the position in an # ordered sequence such as 1st, 2nd, 3rd, 4th. # -- cgit v1.2.3 From b2f34d1e3591df0f19f01ba30160661175c9a6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 23 Sep 2011 16:16:53 +0200 Subject: Ensure that constantize just rescues NameError that applies to the constant being currently loaded. --- .../lib/active_support/inflector/methods.rb | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index b22e39c7c2..dd232a5e2f 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -245,12 +245,15 @@ module ActiveSupport # "blargle".safe_constantize # => nil def safe_constantize(camel_cased_word) begin - camel_cased_word.constantize - rescue NameError - nil + constantize(camel_cased_word) + rescue NameError => e + raise unless e.message =~ /uninitialized constant #{const_regexp(camel_cased_word)}$/ || + e.name.to_s == camel_cased_word.to_s + rescue ArgumentError => e + raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/ end end - + # Turns a number into an ordinal string used to denote the position in an # ordered sequence such as 1st, 2nd, 3rd, 4th. # @@ -273,5 +276,18 @@ module ActiveSupport end end end + + private + + # Mount a regular expression that will match part by part of the constant. + # For instance, Foo::Bar::Baz will generate Foo(::Bar(::Baz)?)? + def const_regexp(camel_cased_word) #:nodoc: + parts = camel_cased_word.split("::") + last = parts.pop + + parts.reverse.inject(last) do |acc, part| + part.empty? ? acc : "#{part}(::#{acc})?" + end + end end end -- cgit v1.2.3 From e8987c30d0dc3ae5903a6d3a6e293641759b6fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 23 Sep 2011 16:46:33 +0200 Subject: Use safe_constantize where possible. --- activesupport/lib/active_support/core_ext/module/reachable.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/module/reachable.rb b/activesupport/lib/active_support/core_ext/module/reachable.rb index 443d2c3d53..5d3d0e9851 100644 --- a/activesupport/lib/active_support/core_ext/module/reachable.rb +++ b/activesupport/lib/active_support/core_ext/module/reachable.rb @@ -3,8 +3,6 @@ require 'active_support/core_ext/string/inflections' class Module def reachable? #:nodoc: - !anonymous? && name.constantize.equal?(self) - rescue NameError - false + !anonymous? && name.safe_constantize.equal?(self) end end -- cgit v1.2.3 From 36699977f2ddbb937aac97998d2d8503499c57e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 23 Sep 2011 16:49:05 +0200 Subject: Update CHANGELOG for safe_constantize. --- activesupport/lib/active_support/inflector/methods.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index dd232a5e2f..934529d496 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -239,10 +239,13 @@ module ActiveSupport # "C".safe_constantize # => 'outside', same as ::C # end # - # nil is returned when the name is not in CamelCase or the constant is + # nil is returned when the name is not in CamelCase or the constant (or part of it) is # unknown. # # "blargle".safe_constantize # => nil + # "UnknownModule".safe_constantize # => nil + # "UnknownModule::Foo::Bar".safe_constantize # => nil + # def safe_constantize(camel_cased_word) begin constantize(camel_cased_word) -- cgit v1.2.3 From 06634f44d0fd106a49d4f7a63bcb1532006e3742 Mon Sep 17 00:00:00 2001 From: Ryan Oblak Date: Fri, 23 Sep 2011 10:21:34 -0700 Subject: Minor doc fix to String#constantize --- activesupport/lib/active_support/core_ext/string/inflections.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index b4218cb42c..c7ceeb9de4 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -36,9 +36,9 @@ class String # or is not initialized. See ActiveSupport::Inflector.constantize # # Examples - # "Module".constantize # => Module - # "Class".constantize # => Class - # "blargle".safe_constantize # => NameError: wrong constant name blargle + # "Module".constantize # => Module + # "Class".constantize # => Class + # "blargle".constantize # => NameError: wrong constant name blargle def constantize ActiveSupport::Inflector.constantize(self) end -- cgit v1.2.3 From f9164749625df8585696857c93484a5b5e2307c6 Mon Sep 17 00:00:00 2001 From: Alexey Vakhov Date: Sat, 24 Sep 2011 23:27:06 +0400 Subject: remove superfluous to_s in ERB::Util.html_escape --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') 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 94999807dd..2daf4016cd 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -20,7 +20,7 @@ class ERB if s.html_safe? s else - s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(//, ">").gsub(/ Date: Thu, 29 Sep 2011 20:07:19 -0500 Subject: Fixing `as_json` method for ActiveRecord models. When you've got an AR Model and you override the `as_json` method, you should be able to add default options to the renderer, like this: class User < ActiveRecord::Base def as_json(options = {}) super(options.merge(:except => [:password_digest])) end end This was not possible before this commit. See the added test case. --- activesupport/lib/active_support/core_ext/object/to_json.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/object/to_json.rb b/activesupport/lib/active_support/core_ext/object/to_json.rb index 14ef27340e..82e232070d 100644 --- a/activesupport/lib/active_support/core_ext/object/to_json.rb +++ b/activesupport/lib/active_support/core_ext/object/to_json.rb @@ -12,7 +12,7 @@ end [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass| klass.class_eval <<-RUBY, __FILE__, __LINE__ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def to_json(options = nil) + def to_json(options = {}) ActiveSupport::JSON.encode(self, options) end RUBY -- cgit v1.2.3 From 37b9594a8e08916e1e9ae9a6aaffc13ef516ad11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 30 Sep 2011 12:45:36 +0200 Subject: Set the default options value for as_json in the encoder object. --- activesupport/lib/active_support/core_ext/object/to_json.rb | 2 +- activesupport/lib/active_support/json/encoding.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/core_ext/object/to_json.rb b/activesupport/lib/active_support/core_ext/object/to_json.rb index 82e232070d..14ef27340e 100644 --- a/activesupport/lib/active_support/core_ext/object/to_json.rb +++ b/activesupport/lib/active_support/core_ext/object/to_json.rb @@ -12,7 +12,7 @@ end [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass| klass.class_eval <<-RUBY, __FILE__, __LINE__ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def to_json(options = {}) + def to_json(options = nil) ActiveSupport::JSON.encode(self, options) end RUBY diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 67698c1cff..469ae69258 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -38,7 +38,7 @@ module ActiveSupport attr_reader :options def initialize(options = nil) - @options = options + @options = options || {} @seen = Set.new end @@ -59,7 +59,7 @@ module ActiveSupport def options_for(value) if value.is_a?(Array) || value.is_a?(Hash) # hashes and arrays need to get encoder in the options, so that they can detect circular references - (options || {}).merge(:encoder => self) + options.merge(:encoder => self) else options end -- cgit v1.2.3