/spec/call_by_name_spec.rb

https://github.com/stonegao/rewrite_rails · Ruby · 267 lines · 215 code · 52 blank · 0 comment · 15 complexity · c8a9b9f1e01ac2e1da09a4edaf768d0a MD5 · raw file

  1. require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb'))
  2. RewriteRails
  3. PROCESSOR_CLASS = RewriteRails::CallByName::ClassProcessor
  4. def ws(str)
  5. str.gsub(/\s+/, ' ')
  6. end
  7. def if_then_by_value(test, consequent)
  8. test && consequent
  9. end
  10. def eval_processed &block
  11. eval(Ruby2Ruby.new.process(
  12. PROCESSOR_CLASS.new.process(RewriteRails.clean(&block))
  13. ))
  14. end
  15. describe PROCESSOR_CLASS do
  16. describe "when a method returning nil is defined" do
  17. before(:each) do
  18. RewriteRails::CallByName.class_eval do
  19. def returning_nil(bar)
  20. bar.do_something()
  21. return nil
  22. end
  23. end
  24. @it = PROCESSOR_CLASS.new
  25. end
  26. it "should convert the method including the return of nil" do
  27. ws(RewriteRails::CallByName.method(:returning_nil).unbind.to_ruby).should ==
  28. ws(proc do |bar|
  29. bar.call.do_something()
  30. return nil
  31. end.to_ruby)
  32. end
  33. end
  34. describe "when a simple method is defined" do
  35. before(:each) do
  36. RewriteRails::CallByName.class_eval do
  37. def foo(bar)
  38. bar
  39. end
  40. def bar(bash, blitz)
  41. bash + blitz
  42. end
  43. end
  44. @it = PROCESSOR_CLASS.new
  45. end
  46. it "should convert the method to use thunks" do
  47. ws(RewriteRails::CallByName.method(:foo).unbind.to_ruby).should == ws(proc { |bar| bar.call }.to_ruby)
  48. end
  49. it "should convert a method call to supply one thunk" do
  50. @it = PROCESSOR_CLASS.new
  51. ws(Ruby2Ruby.new.process(
  52. @it.process(
  53. RewriteRails.clean { foo(1 + 1) }
  54. )
  55. )).should == ws(Ruby2Ruby.new.process(RewriteRails.clean { RewriteRails::CallByName.foo(proc { 1 + 1 }) }))
  56. end
  57. it "should convert a method call to supply multiple thunks" do
  58. @it = PROCESSOR_CLASS.new
  59. ws(Ruby2Ruby.new.process(
  60. @it.process(
  61. RewriteRails.clean { bar(1 + 1, 1 - 1) }
  62. )
  63. )).should == ws(Ruby2Ruby.new.process(RewriteRails.clean { RewriteRails::CallByName.bar(proc { 1 + 1 }, proc { 1 - 1 }) }))
  64. end
  65. describe "maybe" do
  66. before(:each) do
  67. RewriteRails::CallByName.class_eval do
  68. def if_then(test, consequent)
  69. test and consequent
  70. end
  71. end
  72. end
  73. it "should not have side-effects in a false case" do
  74. @it = PROCESSOR_CLASS.new
  75. $foo = nil
  76. eval(Ruby2Ruby.new.process(
  77. @it.process(
  78. RewriteRails.clean { if_then(false, $foo = :foo) }
  79. )
  80. ))
  81. $foo.should be_nil
  82. end
  83. it "should have side-effects in a true case" do
  84. @it = PROCESSOR_CLASS.new
  85. $foo = nil
  86. eval(Ruby2Ruby.new.process(
  87. @it.process(
  88. RewriteRails.clean { if_then(true, $foo = :foo) }
  89. )
  90. ))
  91. $foo.should_not be_nil
  92. end
  93. it "should have side_effects in a normal method case" do
  94. $foo = nil
  95. if_then_by_value(false, $foo = :foo)
  96. $foo.should_not be_nil
  97. end
  98. end
  99. end
  100. describe "return keyword" do
  101. describe "hand rolled" do
  102. before(:each) do
  103. RewriteRails::CallByName.class_eval do
  104. def self.hand_returner(foo)
  105. 1.times do
  106. return foo.call
  107. end
  108. end
  109. end
  110. end
  111. it "should return from inside a block" do
  112. RewriteRails::CallByName.hand_returner(proc { :foo }).should == :foo
  113. end
  114. end
  115. describe "processed" do
  116. before(:each) do
  117. RewriteRails::CallByName.class_eval do
  118. def returner(foo)
  119. 1.times do
  120. return foo
  121. end
  122. end
  123. end
  124. @it = PROCESSOR_CLASS.new
  125. end
  126. it "should return from inside a block" do
  127. eval_processed { returner(:foo) }.should == :foo
  128. end
  129. end
  130. end
  131. describe "splatted methods" do
  132. describe "hand-rolled splatted" do
  133. before(:each) do
  134. RewriteRails::CallByName.class_eval do
  135. def self.try_these(expressions)
  136. (0..(expressions.length - 1)).each do |i|
  137. (return expressions[i]) rescue nil
  138. end
  139. return nil
  140. end
  141. end
  142. end
  143. it "should return nil" do
  144. RewriteRails::CallByName.try_these(
  145. RewriteRails::CallByName::P.new(
  146. proc { raise 'foo' },
  147. proc { raise 'bar' }
  148. )
  149. ).should be_nil
  150. end
  151. it "should return blitz" do
  152. RewriteRails::CallByName.try_these(
  153. RewriteRails::CallByName::P.new(
  154. proc { raise 'foo' },
  155. proc { raise 'bar' },
  156. proc { :blitz }
  157. )
  158. ).should == :blitz
  159. end
  160. end
  161. describe "pure splatted" do
  162. before(:each) do
  163. RewriteRails::CallByName.class_eval do
  164. def try_these(*expressions)
  165. value = token = Object.new
  166. i = 0
  167. while i < expressions.length && value == token do
  168. value = expressions[i] rescue token
  169. i += 1
  170. end
  171. value == token ? nil : value
  172. end
  173. end
  174. @it = PROCESSOR_CLASS.new
  175. end
  176. it "should handle try these" do
  177. RewriteRails::CallByName.try_these(
  178. RewriteRails::CallByName::P.new(
  179. proc { raise 'foo' },
  180. proc { raise 'bar' },
  181. proc { :blitz }
  182. )
  183. ).should == :blitz
  184. end
  185. it "should allow try these to fall through" do
  186. RewriteRails::CallByName.try_these(
  187. RewriteRails::CallByName::P.new(
  188. proc { raise 'foo' },
  189. proc { raise 'bar' },
  190. proc { raise 'blitz' }
  191. )
  192. ).should be_nil
  193. end
  194. end
  195. describe "mixed splatted" do
  196. before(:each) do
  197. RewriteRails::CallByName.class_eval do
  198. def mixed1(foo, *bar)
  199. foo
  200. end
  201. def mixed2(foo, *bar)
  202. bar.first
  203. end
  204. end
  205. @it = PROCESSOR_CLASS.new
  206. end
  207. it "should handle an unsplatted first parameter" do
  208. eval_processed { mixed1(:foo, :bar, :blitz) }.should == :foo
  209. end
  210. it "should handle a simple splatted last parameter" do
  211. eval_processed { mixed2(:foo, :bar, :blitz) }.should == :bar
  212. end
  213. end
  214. end
  215. end