opal-activesupport 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/opal/activesupport/version.rb +1 -1
- data/opal/active_support/core_ext.rb +5 -0
- data/opal/active_support/core_ext/array.rb +1 -0
- data/opal/active_support/core_ext/array/extract_options.rb +29 -0
- data/opal/active_support/core_ext/class.rb +1 -0
- data/opal/active_support/core_ext/class/attribute.rb +129 -0
- data/opal/active_support/core_ext/hash.rb +1 -0
- data/opal/active_support/core_ext/hash/indifferent_access.rb +23 -0
- data/opal/active_support/core_ext/kernel.rb +1 -0
- data/opal/active_support/core_ext/kernel/singleton_class.rb +6 -0
- data/opal/active_support/core_ext/module.rb +1 -0
- data/opal/active_support/core_ext/module/remove_method.rb +15 -0
- data/opal/active_support/core_ext/object.rb +1 -0
- data/opal/active_support/core_ext/object/try.rb +100 -0
- data/opal/active_support/core_ext/string.rb +2 -0
- data/opal/active_support/core_ext/string/inflections.rb +6 -0
- data/opal/active_support/hash_with_indifferent_access.rb +34 -0
- data/opal/active_support/inflector/inflections.rb +33 -0
- data/spec/core_ext/array/extract_options_spec.rb +49 -0
- data/spec/core_ext/class/attribute_spec.rb +90 -0
- data/spec/core_ext/kernel_spec.rb +9 -0
- data/spec/core_ext/module/remove_method_spec.rb +29 -0
- data/spec/core_ext/object/try_spec.rb +102 -0
- data/spec/spec_helper.rb +13 -1
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87d2b460105407cc966e27d833b627f9f35922e1
|
4
|
+
data.tar.gz: 5c55b9cc4c9093242d4944dcf1d414f1f5b9c6a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95d565c00c6a4628ed6baa96cfc735525b76dae8fe3ca8eb985479c936dec6213f1105dd6831ee4bfeea45f08251f16c3c682f13df0d9f32f01031d33abc32c7
|
7
|
+
data.tar.gz: 6b4f61e61dd0ef07188ea84f940dd781144dc64e5965e035be4676d33aea6c4f5c5e95a8cb77b67f6f4f7e1796ae3e93f4633331e606b1a965154a94f92cb960
|
@@ -1,5 +1,10 @@
|
|
1
|
+
require 'active_support/core_ext/array'
|
2
|
+
require 'active_support/core_ext/class'
|
1
3
|
require 'active_support/core_ext/enumerable'
|
4
|
+
require 'active_support/core_ext/hash'
|
2
5
|
require 'active_support/core_ext/integer'
|
6
|
+
require 'active_support/core_ext/kernel'
|
7
|
+
require 'active_support/core_ext/module'
|
3
8
|
require 'active_support/core_ext/numeric'
|
4
9
|
require 'active_support/core_ext/object'
|
5
10
|
require 'active_support/core_ext/string'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/core_ext/array/extract_options'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Hash
|
2
|
+
# By default, only instances of Hash itself are extractable.
|
3
|
+
# Subclasses of Hash may implement this method and return
|
4
|
+
# true to declare themselves as extractable. If a Hash
|
5
|
+
# is extractable, Array#extract_options! pops it from
|
6
|
+
# the Array when it is the last element of the Array.
|
7
|
+
def extractable_options?
|
8
|
+
instance_of?(Hash)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Array
|
13
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
14
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
15
|
+
#
|
16
|
+
# def options(*args)
|
17
|
+
# args.extract_options!
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# options(1, 2) # => {}
|
21
|
+
# options(1, 2, a: :b) # => {:a=>:b}
|
22
|
+
def extract_options!
|
23
|
+
if last.is_a?(Hash) && last.extractable_options?
|
24
|
+
pop
|
25
|
+
else
|
26
|
+
{}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
2
|
+
require 'active_support/core_ext/module/remove_method'
|
3
|
+
require 'active_support/core_ext/array/extract_options'
|
4
|
+
|
5
|
+
class Class
|
6
|
+
# Declare a class-level attribute whose value is inheritable by subclasses.
|
7
|
+
# Subclasses can change their own value and it will not impact parent class.
|
8
|
+
#
|
9
|
+
# class Base
|
10
|
+
# class_attribute :setting
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class Subclass < Base
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Base.setting = true
|
17
|
+
# Subclass.setting # => true
|
18
|
+
# Subclass.setting = false
|
19
|
+
# Subclass.setting # => false
|
20
|
+
# Base.setting # => true
|
21
|
+
#
|
22
|
+
# In the above case as long as Subclass does not assign a value to setting
|
23
|
+
# by performing <tt>Subclass.setting = _something_ </tt>, <tt>Subclass.setting</tt>
|
24
|
+
# would read value assigned to parent class. Once Subclass assigns a value then
|
25
|
+
# the value assigned by Subclass would be returned.
|
26
|
+
#
|
27
|
+
# This matches normal Ruby method inheritance: think of writing an attribute
|
28
|
+
# on a subclass as overriding the reader method. However, you need to be aware
|
29
|
+
# when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
|
30
|
+
# In such cases, you don't want to do changes in places but use setters:
|
31
|
+
#
|
32
|
+
# Base.setting = []
|
33
|
+
# Base.setting # => []
|
34
|
+
# Subclass.setting # => []
|
35
|
+
#
|
36
|
+
# # Appending in child changes both parent and child because it is the same object:
|
37
|
+
# Subclass.setting << :foo
|
38
|
+
# Base.setting # => [:foo]
|
39
|
+
# Subclass.setting # => [:foo]
|
40
|
+
#
|
41
|
+
# # Use setters to not propagate changes:
|
42
|
+
# Base.setting = []
|
43
|
+
# Subclass.setting += [:foo]
|
44
|
+
# Base.setting # => []
|
45
|
+
# Subclass.setting # => [:foo]
|
46
|
+
#
|
47
|
+
# For convenience, an instance predicate method is defined as well.
|
48
|
+
# To skip it, pass <tt>instance_predicate: false</tt>.
|
49
|
+
#
|
50
|
+
# Subclass.setting? # => false
|
51
|
+
#
|
52
|
+
# Instances may overwrite the class value in the same way:
|
53
|
+
#
|
54
|
+
# Base.setting = true
|
55
|
+
# object = Base.new
|
56
|
+
# object.setting # => true
|
57
|
+
# object.setting = false
|
58
|
+
# object.setting # => false
|
59
|
+
# Base.setting # => true
|
60
|
+
#
|
61
|
+
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
62
|
+
#
|
63
|
+
# object.setting # => NoMethodError
|
64
|
+
# object.setting? # => NoMethodError
|
65
|
+
#
|
66
|
+
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
67
|
+
#
|
68
|
+
# object.setting = false # => NoMethodError
|
69
|
+
#
|
70
|
+
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
|
71
|
+
def class_attribute(*attrs)
|
72
|
+
options = attrs.extract_options!
|
73
|
+
instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
|
74
|
+
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
|
75
|
+
instance_predicate = options.fetch(:instance_predicate, true)
|
76
|
+
|
77
|
+
attrs.each do |name|
|
78
|
+
define_singleton_method(name) { nil }
|
79
|
+
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
80
|
+
|
81
|
+
ivar = "@#{name}"
|
82
|
+
|
83
|
+
define_singleton_method("#{name}=") do |val|
|
84
|
+
singleton_class.class_eval do
|
85
|
+
remove_possible_method(name)
|
86
|
+
define_method(name) { val }
|
87
|
+
end
|
88
|
+
|
89
|
+
if singleton_class?
|
90
|
+
class_eval do
|
91
|
+
remove_possible_method(name)
|
92
|
+
define_method(name) do
|
93
|
+
if instance_variable_defined? ivar
|
94
|
+
instance_variable_get ivar
|
95
|
+
else
|
96
|
+
singleton_class.send name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
val
|
102
|
+
end
|
103
|
+
|
104
|
+
if instance_reader
|
105
|
+
remove_possible_method name
|
106
|
+
define_method(name) do
|
107
|
+
if instance_variable_defined?(ivar)
|
108
|
+
instance_variable_get ivar
|
109
|
+
else
|
110
|
+
self.class.public_send name
|
111
|
+
end
|
112
|
+
end
|
113
|
+
define_method("#{name}?") { !!public_send(name) } if instance_predicate
|
114
|
+
end
|
115
|
+
|
116
|
+
attr_writer name if instance_writer
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
unless respond_to?(:singleton_class?)
|
123
|
+
def singleton_class?
|
124
|
+
# Opal doesn't place singleton at ancestors.first. Returning true here
|
125
|
+
# seems to work in Opal anyway.
|
126
|
+
true || ancestors.first != self
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
|
5
|
+
# Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
|
6
|
+
#
|
7
|
+
# { a: 1 }.with_indifferent_access['a'] # => 1
|
8
|
+
def with_indifferent_access
|
9
|
+
ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Called when object is nested under an object that receives
|
13
|
+
# #with_indifferent_access. This method will be called on the current object
|
14
|
+
# by the enclosing object and is aliased to #with_indifferent_access by
|
15
|
+
# default. Subclasses of Hash may overwrite this method to return +self+ if
|
16
|
+
# converting to an <tt>ActiveSupport::HashWithIndifferentAccess</tt> would not be
|
17
|
+
# desirable.
|
18
|
+
#
|
19
|
+
# b = { b: 1 }
|
20
|
+
# { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
|
21
|
+
# # => {"b"=>1}
|
22
|
+
alias nested_under_indifferent_access with_indifferent_access
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_support/core_ext/module/remove_method'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Module
|
2
|
+
# Removes the named method, if it exists.
|
3
|
+
def remove_possible_method(method)
|
4
|
+
if method_defined?(method) || private_method_defined?(method)
|
5
|
+
undef_method(method)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Replaces the existing method definition, if there is one, with the passed
|
10
|
+
# block as its body.
|
11
|
+
def redefine_method(method, &block)
|
12
|
+
remove_possible_method(method)
|
13
|
+
define_method(method, &block)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class Object
|
2
|
+
# Invokes the public method whose name goes as first argument just like
|
3
|
+
# +public_send+ does, except that if the receiver does not respond to it the
|
4
|
+
# call returns +nil+ rather than raising an exception.
|
5
|
+
#
|
6
|
+
# This method is defined to be able to write
|
7
|
+
#
|
8
|
+
# @person.try(:name)
|
9
|
+
#
|
10
|
+
# instead of
|
11
|
+
#
|
12
|
+
# @person.name if @person
|
13
|
+
#
|
14
|
+
# +try+ calls can be chained:
|
15
|
+
#
|
16
|
+
# @person.try(:spouse).try(:name)
|
17
|
+
#
|
18
|
+
# instead of
|
19
|
+
#
|
20
|
+
# @person.spouse.name if @person && @person.spouse
|
21
|
+
#
|
22
|
+
# +try+ will also return +nil+ if the receiver does not respond to the method:
|
23
|
+
#
|
24
|
+
# @person.try(:non_existing_method) #=> nil
|
25
|
+
#
|
26
|
+
# instead of
|
27
|
+
#
|
28
|
+
# @person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil
|
29
|
+
#
|
30
|
+
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
|
31
|
+
# to the method:
|
32
|
+
#
|
33
|
+
# nil.try(:to_i) # => nil, rather than 0
|
34
|
+
#
|
35
|
+
# Arguments and blocks are forwarded to the method if invoked:
|
36
|
+
#
|
37
|
+
# @posts.try(:each_slice, 2) do |a, b|
|
38
|
+
# ...
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# The number of arguments in the signature must match. If the object responds
|
42
|
+
# to the method the call is attempted and +ArgumentError+ is still raised
|
43
|
+
# in case of argument mismatch.
|
44
|
+
#
|
45
|
+
# If +try+ is called without arguments it yields the receiver to a given
|
46
|
+
# block unless it is +nil+:
|
47
|
+
#
|
48
|
+
# @person.try do |p|
|
49
|
+
# ...
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# You can also call try with a block without accepting an argument, and the block
|
53
|
+
# will be instance_eval'ed instead:
|
54
|
+
#
|
55
|
+
# @person.try { upcase.truncate(50) }
|
56
|
+
#
|
57
|
+
# Please also note that +try+ is defined on +Object+. Therefore, it won't work
|
58
|
+
# with instances of classes that do not have +Object+ among their ancestors,
|
59
|
+
# like direct subclasses of +BasicObject+. For example, using +try+ with
|
60
|
+
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
|
61
|
+
# the delegator itself.
|
62
|
+
def try(*a, &b)
|
63
|
+
try!(*a, &b) if a.empty? || respond_to?(a.first)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Same as #try, but will raise a NoMethodError exception if the receiver is not +nil+ and
|
67
|
+
# does not implement the tried method.
|
68
|
+
|
69
|
+
def try!(*a, &b)
|
70
|
+
if a.empty? && block_given?
|
71
|
+
if b.arity.zero?
|
72
|
+
instance_eval(&b)
|
73
|
+
else
|
74
|
+
yield self
|
75
|
+
end
|
76
|
+
else
|
77
|
+
public_send(*a, &b)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class NilClass
|
83
|
+
# Calling +try+ on +nil+ always returns +nil+.
|
84
|
+
# It becomes especially helpful when navigating through associations that may return +nil+.
|
85
|
+
#
|
86
|
+
# nil.try(:name) # => nil
|
87
|
+
#
|
88
|
+
# Without +try+
|
89
|
+
# @person && @person.children.any? && @person.children.first.name
|
90
|
+
#
|
91
|
+
# With +try+
|
92
|
+
# @person.try(:children).try(:first).try(:name)
|
93
|
+
def try(*args)
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def try!(*args)
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
1
3
|
class String
|
2
4
|
def pluralize
|
3
5
|
ActiveSupport::Inflector.pluralize(self)
|
@@ -6,4 +8,8 @@ class String
|
|
6
8
|
def singularize
|
7
9
|
ActiveSupport::Inflector.singularize(self)
|
8
10
|
end
|
11
|
+
|
12
|
+
def constantize
|
13
|
+
ActiveSupport::Inflector.constantize(self)
|
14
|
+
end
|
9
15
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
class HashWithIndifferentAccess < Hash
|
3
|
+
# Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
|
4
|
+
# this class.
|
5
|
+
def extractable_options?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_indifferent_access
|
10
|
+
dup
|
11
|
+
end
|
12
|
+
|
13
|
+
def nested_under_indifferent_access
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(constructor = {})
|
18
|
+
if constructor.respond_to?(:to_hash)
|
19
|
+
super()
|
20
|
+
update(constructor)
|
21
|
+
else
|
22
|
+
super(constructor)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.new_from_hash_copying_default(hash)
|
27
|
+
hash = hash.to_hash
|
28
|
+
new(hash).tap do |new_hash|
|
29
|
+
new_hash.default = hash.default
|
30
|
+
new_hash.default_proc = hash.default_proc if hash.default_proc
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module Inflector
|
3
5
|
extend self
|
@@ -10,6 +12,37 @@ module ActiveSupport
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
15
|
+
def constantize(camel_cased_word)
|
16
|
+
names = camel_cased_word.split('::')
|
17
|
+
|
18
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
19
|
+
Object.const_get(camel_cased_word) if names.empty?
|
20
|
+
|
21
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
22
|
+
names.shift if names.size > 1 && names.first.empty?
|
23
|
+
|
24
|
+
names.inject(Object) do |constant, name|
|
25
|
+
if constant == Object
|
26
|
+
constant.const_get(name)
|
27
|
+
else
|
28
|
+
candidate = constant.const_get(name)
|
29
|
+
next candidate if constant.const_defined?(name, false)
|
30
|
+
next candidate unless Object.const_defined?(name)
|
31
|
+
|
32
|
+
# Go down the ancestors to check if it is owned directly. The check
|
33
|
+
# stops when we reach Object or the end of ancestors tree.
|
34
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
35
|
+
break const if ancestor == Object
|
36
|
+
break ancestor if ancestor.const_defined?(name, false)
|
37
|
+
const
|
38
|
+
end
|
39
|
+
|
40
|
+
# owner is in Object, so raise
|
41
|
+
constant.const_get(name, false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
13
46
|
def pluralize(word)
|
14
47
|
apply_inflections(word, inflections.plurals)
|
15
48
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# require 'abstract_unit'
|
4
|
+
# require 'active_support/core_ext/array'
|
5
|
+
# require 'active_support/core_ext/hash'
|
6
|
+
|
7
|
+
class HashSubclass < Hash
|
8
|
+
end
|
9
|
+
|
10
|
+
class ExtractableHashSubclass < Hash
|
11
|
+
def extractable_options?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Array do
|
17
|
+
describe '#extract_options!' do
|
18
|
+
it 'extracts options' do
|
19
|
+
assert_equal({}, [].extract_options!)
|
20
|
+
assert_equal({}, [1].extract_options!)
|
21
|
+
assert_equal({ a: :b }, [{ a: :b }].extract_options!)
|
22
|
+
assert_equal({ a: :b }, [1, { a: :b }].extract_options!)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'doesnt extract hash subclasses' do
|
26
|
+
hash = HashSubclass.new
|
27
|
+
hash[:foo] = 1
|
28
|
+
array = [hash]
|
29
|
+
options = array.extract_options!
|
30
|
+
assert_equal({}, options)
|
31
|
+
assert_equal([hash], array)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'extracts extractable subclass' do
|
35
|
+
hash = ExtractableHashSubclass.new
|
36
|
+
hash[:foo] = 1
|
37
|
+
array = [hash]
|
38
|
+
options = array.extract_options!
|
39
|
+
assert_equal({ foo: 1 }, options)
|
40
|
+
assert_equal([], array)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'extracts hash with indifferent access' do
|
44
|
+
array = [{ foo: 1 }.with_indifferent_access]
|
45
|
+
options = array.extract_options!
|
46
|
+
assert_equal(1, options[:foo])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Class do
|
4
|
+
before do
|
5
|
+
@klass = Class.new { class_attribute :setting }
|
6
|
+
@sub = Class.new(@klass)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'defaults to nil' do
|
10
|
+
assert_nil @klass.setting
|
11
|
+
assert_nil @sub.setting
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'inheritable' do
|
15
|
+
@klass.setting = 1
|
16
|
+
assert_equal 1, @sub.setting
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'overridable' do
|
20
|
+
@sub.setting = 1
|
21
|
+
assert_nil @klass.setting
|
22
|
+
|
23
|
+
@klass.setting = 2
|
24
|
+
assert_equal 1, @sub.setting
|
25
|
+
|
26
|
+
assert_equal 1, Class.new(@sub).setting
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'predicate method' do
|
30
|
+
assert_equal false, @klass.setting?
|
31
|
+
@klass.setting = 1
|
32
|
+
assert_equal true, @klass.setting?
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'instance reader delegates to class' do
|
36
|
+
assert_nil @klass.new.setting
|
37
|
+
|
38
|
+
@klass.setting = 1
|
39
|
+
assert_equal 1, @klass.new.setting
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'instance override' do
|
43
|
+
object = @klass.new
|
44
|
+
object.setting = 1
|
45
|
+
assert_nil @klass.setting
|
46
|
+
@klass.setting = 2
|
47
|
+
assert_equal 1, object.setting
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'instance predicate' do
|
51
|
+
object = @klass.new
|
52
|
+
assert_equal false, object.setting?
|
53
|
+
object.setting = 1
|
54
|
+
assert_equal true, object.setting?
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'disabling instance writer' do
|
58
|
+
object = Class.new { class_attribute :setting, :instance_writer => false }.new
|
59
|
+
assert_raise(NoMethodError) { object.setting = 'boom' }
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'disabling instance reader' do
|
63
|
+
object = Class.new { class_attribute :setting, :instance_reader => false }.new
|
64
|
+
assert_raise(NoMethodError) { object.setting }
|
65
|
+
assert_raise(NoMethodError) { object.setting? }
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'disabling both instance writer and reader' do
|
69
|
+
object = Class.new { class_attribute :setting, :instance_accessor => false }.new
|
70
|
+
assert_raise(NoMethodError) { object.setting }
|
71
|
+
assert_raise(NoMethodError) { object.setting? }
|
72
|
+
assert_raise(NoMethodError) { object.setting = 'boom' }
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'disabling instance predicate' do
|
76
|
+
object = Class.new { class_attribute :setting, instance_predicate: false }.new
|
77
|
+
assert_raise(NoMethodError) { object.setting? }
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'works well with singleton classes' do
|
81
|
+
object = @klass.new
|
82
|
+
object.singleton_class.setting = 'foo'
|
83
|
+
assert_equal 'foo', object.setting
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'setter returns set value' do
|
87
|
+
val = @klass.send(:setting=, 1)
|
88
|
+
assert_equal 1, val
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RemoveMethodTests
|
4
|
+
class A
|
5
|
+
def do_something
|
6
|
+
return 1
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Module do
|
12
|
+
describe '#remove_possible_method' do
|
13
|
+
it 'removes method from an object' do
|
14
|
+
RemoveMethodTests::A.class_eval{
|
15
|
+
self.remove_possible_method(:do_something)
|
16
|
+
}
|
17
|
+
assert !RemoveMethodTests::A.new.respond_to?(:do_something)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#redefine_method' do
|
22
|
+
it 'redefines method in an object' do
|
23
|
+
RemoveMethodTests::A.class_eval{
|
24
|
+
self.redefine_method(:do_something) { return 100 }
|
25
|
+
}
|
26
|
+
assert_equal 100, RemoveMethodTests::A.new.do_something
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Object do
|
4
|
+
describe '#try' do
|
5
|
+
before do
|
6
|
+
@string = "Hello"
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'nonexisting method' do
|
10
|
+
method = :undefined_method
|
11
|
+
assert !@string.respond_to?(method)
|
12
|
+
assert_nil @string.try(method)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'nonexisting method with arguments' do
|
16
|
+
method = :undefined_method
|
17
|
+
assert !@string.respond_to?(method)
|
18
|
+
assert_nil @string.try(method, 'llo', 'y')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'nonexisting method bang' do
|
22
|
+
method = :undefined_method
|
23
|
+
assert !@string.respond_to?(method)
|
24
|
+
assert_raise(NoMethodError) { @string.try!(method) }
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'nonexisting method with arguments bang' do
|
28
|
+
method = :undefined_method
|
29
|
+
assert !@string.respond_to?(method)
|
30
|
+
assert_raise(NoMethodError) { @string.try!(method, 'llo', 'y') }
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'valid method' do
|
34
|
+
assert_equal 5, @string.try(:size)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'argument forwarding' do
|
38
|
+
assert_equal 'Hey', @string.try(:sub, 'llo', 'y')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'block forwarding' do
|
42
|
+
assert_equal 'Hey', @string.try(:sub, 'llo') { |match| 'y' }
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'nil to type' do
|
46
|
+
assert_nil nil.try(:to_s)
|
47
|
+
assert_nil nil.try(:to_i)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'false try' do
|
51
|
+
assert_equal 'false', false.try(:to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'try only block' do
|
55
|
+
assert_equal @string.reverse, @string.try { |s| s.reverse }
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'try only block bang' do
|
59
|
+
assert_equal @string.reverse, @string.try! { |s| s.reverse }
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'try only block nil' do
|
63
|
+
ran = false
|
64
|
+
nil.try { ran = true }
|
65
|
+
assert_equal false, ran
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'try with instance eval block' do
|
69
|
+
assert_equal @string.reverse, @string.try { reverse }
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'try with instance eval block bang' do
|
73
|
+
assert_equal @string.reverse, @string.try! { reverse }
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'try with private method bang' do
|
77
|
+
klass = Class.new do
|
78
|
+
private
|
79
|
+
|
80
|
+
def private_method
|
81
|
+
'private method'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Opal doesn't currently support private methods
|
86
|
+
# assert_raise(NoMethodError) { klass.new.try!(:private_method) }
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'try with private method' do
|
90
|
+
klass = Class.new do
|
91
|
+
private
|
92
|
+
|
93
|
+
def private_method
|
94
|
+
'private method'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Opal doesn't currently support private methods
|
99
|
+
# assert_nil klass.new.try(:private_method)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,8 +3,20 @@ require 'opal-activesupport'
|
|
3
3
|
require 'active_support/inflector'
|
4
4
|
|
5
5
|
module TestUnitHelpers
|
6
|
+
def assert actual
|
7
|
+
expect(actual).to be_truthy
|
8
|
+
end
|
9
|
+
|
10
|
+
def assert_nil actual
|
11
|
+
expect(actual).to be_nil
|
12
|
+
end
|
13
|
+
|
6
14
|
def assert_equal actual, expected
|
7
|
-
|
15
|
+
expect(expected).to eq(actual)
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_raise error, &block
|
19
|
+
expect(&block).to raise_error(error)
|
8
20
|
end
|
9
21
|
end
|
10
22
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-activesupport
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elia Schito
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -76,24 +76,41 @@ files:
|
|
76
76
|
- opal-activesupport.gemspec
|
77
77
|
- opal/active_support.rb
|
78
78
|
- opal/active_support/core_ext.rb
|
79
|
+
- opal/active_support/core_ext/array.rb
|
80
|
+
- opal/active_support/core_ext/array/extract_options.rb
|
81
|
+
- opal/active_support/core_ext/class.rb
|
82
|
+
- opal/active_support/core_ext/class/attribute.rb
|
79
83
|
- opal/active_support/core_ext/enumerable.rb
|
84
|
+
- opal/active_support/core_ext/hash.rb
|
85
|
+
- opal/active_support/core_ext/hash/indifferent_access.rb
|
80
86
|
- opal/active_support/core_ext/integer.rb
|
81
87
|
- opal/active_support/core_ext/integer/time.rb
|
88
|
+
- opal/active_support/core_ext/kernel.rb
|
89
|
+
- opal/active_support/core_ext/kernel/singleton_class.rb
|
90
|
+
- opal/active_support/core_ext/module.rb
|
91
|
+
- opal/active_support/core_ext/module/remove_method.rb
|
82
92
|
- opal/active_support/core_ext/numeric.rb
|
83
93
|
- opal/active_support/core_ext/numeric/calculations.rb
|
84
94
|
- opal/active_support/core_ext/numeric/time.rb
|
85
95
|
- opal/active_support/core_ext/object.rb
|
86
96
|
- opal/active_support/core_ext/object/blank.rb
|
87
97
|
- opal/active_support/core_ext/object/json.rb
|
98
|
+
- opal/active_support/core_ext/object/try.rb
|
88
99
|
- opal/active_support/core_ext/string.rb
|
89
100
|
- opal/active_support/core_ext/string/inflections.rb
|
101
|
+
- opal/active_support/hash_with_indifferent_access.rb
|
90
102
|
- opal/active_support/inflections.rb
|
91
103
|
- opal/active_support/inflector.rb
|
92
104
|
- opal/active_support/inflector/inflections.rb
|
93
105
|
- opal/active_support/time.rb
|
94
106
|
- opal/opal-activesupport.rb
|
107
|
+
- spec/core_ext/array/extract_options_spec.rb
|
108
|
+
- spec/core_ext/class/attribute_spec.rb
|
109
|
+
- spec/core_ext/kernel_spec.rb
|
110
|
+
- spec/core_ext/module/remove_method_spec.rb
|
95
111
|
- spec/core_ext/numeric_spec.rb
|
96
112
|
- spec/core_ext/object/blank_spec.rb
|
113
|
+
- spec/core_ext/object/try_spec.rb
|
97
114
|
- spec/core_ext/string_spec.rb
|
98
115
|
- spec/empty_bool.rb
|
99
116
|
- spec/inflector_test_cases.rb
|
@@ -122,15 +139,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
139
|
version: '0'
|
123
140
|
requirements: []
|
124
141
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.4.5
|
142
|
+
rubygems_version: 2.4.5.1
|
126
143
|
signing_key:
|
127
144
|
specification_version: 4
|
128
145
|
summary: The port of the glorious ActiveSupport for Opal
|
129
146
|
test_files:
|
147
|
+
- spec/core_ext/array/extract_options_spec.rb
|
148
|
+
- spec/core_ext/class/attribute_spec.rb
|
149
|
+
- spec/core_ext/kernel_spec.rb
|
150
|
+
- spec/core_ext/module/remove_method_spec.rb
|
130
151
|
- spec/core_ext/numeric_spec.rb
|
131
152
|
- spec/core_ext/object/blank_spec.rb
|
153
|
+
- spec/core_ext/object/try_spec.rb
|
132
154
|
- spec/core_ext/string_spec.rb
|
133
155
|
- spec/empty_bool.rb
|
134
156
|
- spec/inflector_test_cases.rb
|
135
157
|
- spec/spec_helper.rb
|
136
|
-
has_rdoc:
|