opal-activesupport 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|