I recently had a problem with rake gems:install with a fresh rails app. Rakefile bootstraps the full rails environment, including plugins, controllers, etc. Some of the code getting executed depended on a gem, but I was running “rake gem:install” to install those gems. A circular “chicken or the egg” problem!
Here was my solution, which I put in environment.rb
unless $0 =~ /rake/
# ... require code that relies on certain gems
end
So in a flash of inspiration on the airplane last week, I jotted down a new version of my shoulda params pattern. Put this pastie in test/shoulda_macros/request_params.rb
The general idea is this:
a_get_to(:index) do
with_params( {:foo => 'bar'}, "valid params" ) do
should_respond_with :success
with_params( :more => 'nested stuff' ) do
should "do something extra special" do
assert true
end
end
end
end
Here’s what it looks like in action, taken from the ScrumNinja.com code:
require File.dirname(__FILE__) + '/../test_helper'
class MainControllerTest < ActionController::TestCase
@@message = "you guys rock!"
context "When not logged in" do
setup do
login_as( nil )
end
%w[ index tour contact api ].each do |action|
a_get_to( action, params=false ) do
should_respond_with :success
end
end
a_get_to( :feedback, params=false ) do
should_redirect_to "'/login'"
end
a_post_to( :contact, :message => @@message ) do
should_send_email :to => "Mailer::GO_EMAIL", :body => %r{#@@message}
should_redirect_to "'/'"
end
end
context "When logged in" do
setup do
login_as( @user = create_user )
end
a_post_to( :feedback, :message => @@message ) do
should_send_email :to => "Mailer::GO_EMAIL", :body => %r{#@@message}
should_respond_with :redirect
end
end
end
Factories-and-workers is now updated to not only be a plugin, but also a gem. Thanks to Jonathan Barket and Nick Hoffman for their help!
It is also now automatically loaded for test and development environments (as a plugin, or do it manually as below with the unless statement). I find this really comes in handy for using it in the rails console to populate your database.
Get It
Add it as a gem dependency to your rails environment.rb:
config.gem 'dfl-factories-and-workers', :lib => 'factories-and-workers', :source => 'http://gems.github.com' unless RAILS_ENV=='production'
Or install it as a gem manually:
gem sources -a http://gems.github.com sudo gem install dfl-factories-and-workers
Or grab the source:
git clone git://github.com/dfl/factories-and-workers.git
so I’m surprised I didn’t figure this out earlier… it was this message that finally drove the point home.
When using haml in your rails view templates, you do not need to close ruby blocks and conditional statements.
for example:
Here's how I was doing it before:
- content_for :head do
= stylesheet_link_tag 'jquery.autocomplete'
= javascript_include_tag 'jquery.autocomplete'
- end
- javascript_behaviour '$("input#user_full_name").autocomplete("project_roles/auto_complete_for_user_full_name")'
And here's how it really should be:
- content_for :head do
= stylesheet_link_tag 'jquery.autocomplete'
= javascript_include_tag 'jquery.autocomplete'
- javascript_behaviour '$("input#user_full_name").autocomplete("project_roles/auto_complete_for_user_full_name")'
So much nicer and readable, just as the haml gods intended :)
+1 for making ”- end” an error.
UPDATE:
On Oct 10, 2008, at 5:18 PM, Nathan Weizenbaum wrote: ”- end” actually is an error in the most recent Haml release, 2.0.3.
I shared some tips with a colleague who is relatively new to rails, and thought I’d post them here too.
##before:
content_tag :div, @event.description_html unless @event.description_html.to_s.blank?
## better:
# blank works on nil, string, array, and hash. It's a rails thing from ActiveSupport.
content_tag :div, @event.description_html unless @event.description_html.blank?
## best:
#But even better is to use the special #{attribute}? methods which we get with Rails 2. These basically just call !#{attribute}.blank?
content_tag :div, @event.description_html if @event.description?
the returning method is also handy at times… also from ActiveSupport. Here is an abstracted example from a rails helper: I’m not sure why yet, but returning doesn’t seem to work with strings
## before:
html = ""
html += "some stuff" if some_condition
html += "123"
html
## after:
returning [] do |html|
html << "some stuff" if some_condition
html << "123"
end.join("\n")
and also the pluralize method is part of ActionView::Helpers
## before:
def people_or_person(count)
(count == 1) ? 'person' : 'people'
end
## after:
pluralize count, "person"
using case…
## before:
word.each_char do |x|
if ((x =~ /[a-zA-Z]/) == 0)
str << "[#{x.to_s.downcase}#{x.to_s.upcase}]"
else
str << "[#{x}]"
end
end
## after:
word.each_char do |x|
case x
when /[a-zA-Z]/
str << "[#{x.to_s.downcase}#{x.to_s.upcase}]"
else
str << "[#{x}]"
end
end
using map_with_index (or the closest thing we have in Ruby 1.8) aka collect_with_index
## before:
roles = []
@events_summary[:role_groups].each_with_index do |role, idx|
roles << [role[:for], idx]
end
roles
## after:
require 'enumerator'
@events_summary[:role_groups].enum_with_index.map{ |role, idx| [ role[:for], idx ] }
## Ruby 1.9:
@events_summary[:role_groups].map.with_index{ |role, idx| [ role[:for], idx ] }
require 'rubygems'
require 'activesupport'
# this doesn't work as expected. does anyone know why?
z = returning html="" do
html += "stuff"
html += "more stuff" if true
end
p z
#>> ""
# this works though
z = returning html=[] do
html << "stuff"
html << "more_stuff" if true
end.join("\n")
p z
#>> "stuff\nmore_stuff"
Update: Thanks DrMark, I should have done it like this:
(I didn’t realize that one could use << on strings)
z = returning html="" do
html << "stuff"
html << " more stuff" if true
end
So I just switched over one of our projects to jQuery this weekend, to see what all the hype is about. It’s pretty good. Most notable is that jQuery $() is the same as Prototype $$() [find by CSS selector]. There seems to be no equivalent to Prototype’s $() [find by dom id]. The switch is as simple as adding # [dom id selector] in front of your old prototype $() methods.
jRails is pretty good, I’d say it was 95% plug and play. Just a few quirks where I had to modify some parameters to my helper method calls.
I recently developed this pattern in order to clean up my tests and shoulda contexts. The initial inspiration was that I needed a global parameter to be passed all the time, for security purposes. Then I figured I could also use it with my nested contexts, to get cleaner tests. The special sauce is the overloading of get and post methods, which merges with the @params instance variable. I am also using the @action variable to hold a proc, so that I can keep my tests DRYer. Please let me know what you think in the comments!
PS also notice the use of the slick new should_change macro, which assists me in keeping to one assert per should (and not having to put assert_difference blocks in my setups). (thanks to Ryan McGeary! lighthouse ticket, github commit )
require File.dirname(__FILE__) + '/../test_helper'
require 'events_controller'
require "test/unit"
# Re-raise errors caught by the controller.
class EventsController; def rescue_action(e) raise e end; end
class EventsControllerTest < Test::Unit::TestCase
## special sauce for global parameters
[ :get, :post ].each do |overloaded_method|
define_method overloaded_method do |*args|
action,params,extras = *args
super action, @params.merge( params || {} ), *extras
end
end
def setup
@controller = EventsController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@event = create_event
@user = User.first || create_user
@params = {:security_token => 'abc123' } # add any global params you need here
end
context "A POST to :rsvp" do
setup do
@action = lambda{ post :rsvp, :id => @event.id }
end
context "with no RSVP existing in DB" do
setup do
if rsvp = @user.rsvps.find_by_event_id( @event.id )
rsvp.destroy
end
end
%w[ attending not_attending maybe_attending ].each do |status|
context "with :status = '#{status}'" do
setup do
@params[:status] = status
@action.call
end
should_respond_with :success
should_change "Rsvp.count", :by => 1
should "create the proper Rsvp object" do
assert Rsvp.find_by_user_id_and_event_id_and_status( @user.id, @event.id, status )
end
end
end
end
context "with an existing RSVP in DB" do
setup do
@rsvp = create_rsvp( :event_id => @event.id, :user_id => @user.id, :status => 'not_attending' )
end
context "" do # HACK: this blank context is needed to separate the create_rsvp from the should_not_change call (without it, the count would change by 1)
setup do
@params[:status] = 'attending'
@action.call
end
should_respond_with :success
should_not_change "Rsvp.count"
should "update the status" do
assert_equal @params[:status], @rsvp.reload.status
end
end
end
end
context "a POST to :create" do
setup do
@action = lambda{ post :create }
end
context "when the form fields are blank" do
setup do
@params[:event] = {}
end
should_respond_with :success
should_render_template :edit
should "show validation errors" do
assert_select '.fieldWithErrors'
end
end
context "with valid params and :publish => true" do
setup do
@params[:event] = { :title => "Some New Event", :starts_on => Date.today, :all_day => true, :ends_on => Date.today+1 }
@params[:publish] = true
@action.call
end
should "show up in event index" do
@event = Event.find_by_title("Some New Event")
assert Event.visible.include?( @event )
end
context "and no end date" do
setup do
@params[:ends_on] = nil
@action.call
end
should_respond_with :success
should_render_template :show
should "show up in event index" do
@event = Event.find_by_title("Some New Event")
assert Event.visible.include?( @event )
end
end
end
end
end
I recently needed to iterate over all the ActiveRecord models in the rake factory:generate task for factories-and-workers.
I originally tried to iterate over Object.constants (like John Philip Green’s find_invalid rake task) but that seemed a bit clunky to me, and didn’t really work for my purposes.
Here’s how I did it:
all_models = Dir.glob( File.join( RAILS_ROOT, 'app', 'models', '*.rb') ).map{|path| path[/.+\/(.+).rb/,1] }
AR_models = all_model_names.select{|m| m.classify.constantize < ActiveRecord::Base}
I’ve been working more on factories-and-workers
Yesterday I came up with the idea to make a rake task to ease the initial entry into factory-land. It grabs info from the schema, via the model.columns hash, and prints out a factory template, to be pasted and edited in your factories.rb file.
Check it out:
dfl% rake factory:generate MODEL=task_estimate
factory :task_estimate, {
:task => :belongs_to_model,
:date => lambda{ Time.zone.today - 7 },
:hours => 1.23,
}
If called without the MODEL argument, it will print factory templates for all models.
I previously posted about my friendly_fixtures plugin
It’s now available at github: http://github.com/dfl/friendly_fixtures/tree/master
factories-and-workers at github
Factories and Workers is a Rails plugin originally written by Nathan Herald @ myobie.com after being inspired by Dan Manges’ blog post on factories. It uses some slick metaprogramming to generate factory methods for your ActiveRecord models. Over the past few months I’ve refactored the code, added a bunch of new features, and most importantly wrote some tests!
See it in action:
>> factory :monkey, { :name => "George" }
=> #<FactoryBuilder:0x1a4f2a8>
>> valid_monkey_attributes
=> {:name=>"George"}
>> build_monkey
=> #<Monkey id: nil, name: "George">
>> build_monkey( :name => "Bob" )
=> #<Monkey id: nil, name: "Bob">
>> Monkey.count
=> 0
>> create_monkey
=> #<Monkey id: 1, name: "George">
>> Monkey.count
=> 1
There’s much more info in the README.
An issue came up yesterday that involved an strange nil error, where an attribute was being delegated to a nil association.
I recalled reading this ticket opened by court3nay from caboo.se and thought it might come in handy for others if I put it in the blogosphere.
The ticket ended up being closed because it was deemed unnecessary. Someone with the moniker “protocool” (presumably trevor at http://protocool.com/) shared the final solution which works out of the box with no patches. It goes something like this:
delegate :some_method, :to => '(some_association or return nil)'
The cool thing about this solution, over the proposed patch, is that you can do whatever you like (rather than simply return nil), such as return a default value or raise a custom exception.
I just came across this cool tip from Tom Preston-Werner of rubyisawesome.com. Basically, if you end a mysql commandline query with \G instead of a semicolon, you’ll get a nicely formatted query that is suitable for pasting into a YAML file.
But what if you are not using mysql? We have a project with postgres. There’s probably a psql command to do something similar, but there is also a database agnostic way: Just use the rails console! :)
>> puts User.find(:all).to_yaml
---
- !ruby/object:User
attributes:
status: unverified
salt: L52b2pxGCL
can_invite: "0"
hashed_password: L50/yIQjPCBiU
is_admin: "0"
id: "478674008"
first_name: Mickey
last_name: Mouse
watchlist_by_email: "0"
created_at: 2008-01-30 15:34:26
email: mickey@mouse.com
I’ve been playing with block helpers for some time now, and I love them for their semantic goodness and clarity.
I know that Rails 2 has an assert_email method, which plays nicely with assert_select assert_select_email method.
However, as far as I could tell, this doesn’t allow you to assert any of the headers such as to, from, etc.
Enter assert_emails_sent:
def test_send_crash_data
device_id = 2
assert_email_sent :to => AdminNotifier::CLIENT_CRASH_EMAIL,
:from => AdminNotifier::SYSTEM_EMAIL,
:subject => "Application crashed.",
:body => /device id #{device_id} crashed.+whoops I crashed/ do
AdminNotifier.deliver_send_crash_data('whoops I crashed', device_id)
end
end
- One cool feature is that the values of :to and :from will be automagically sent #email, so you can just say :to => @user, as long as @user.responds_to?(:email).
- Another bonus feature is that you can use either strings or regexps.
grab the code here.
I was suffering with a problem running tests inside of textmate on a Rails 2 project, until I found this comment by David Vrensk at the bottom of this blog post by Rob Sanheim:
Posted by David Vrensk 18 January 2008 @ 9am
I think the easiest solution can be gleaned from the TM ticket that you link to (http://macromates.com/ticket/show?ticket_id=F4DA8B03). I just modify test/test_helper.rb in my current projects so that it starts with
$:.reject! { |e| e.include? ‘TextMate’ }
No patching the distros, and svn still works the way it should.
I like to use factory test helpers to generate attributes which I then pass to ActiveRecord. The default output is expected to be valid (hence the usage with create-bang below). If you want to override any of the defaults, you can simply use Hash#merge.
Here’s an example, using shoulda. It should be pretty clear how it can be applied to vanilla Test::Unit (or the testing framework du jour ;).
## I put this in test_helper.rb so I can use it across all tests. ## You could put it in the actual derived test class as well. def valid_user_attrs( unique = DateTime.now ) { :email => "{unique.hash.abs}@example.com", :first_name => "dummy", :last_name => "user_#{unique}", :profile_attributes => valid_profile_attrs } end def valid_profile_attrs ... end## Here’s the actual test caseclass UserTest < Test::Rails::TestCase context "Two Users" do setup do @user = User.create!( valid_user_attrs ) @user2 = User.create!( valid_user_attrs.merge( :email => "dummy123@dummy.com" ) ) end should "not be friends" do assert !@user.friends.include?( @user2 ) assert !@user2.friends.include?( @user ) end end end
In a previous post, I posted a monkey patch to enhance the behavior of fixtures. I converted it into a plugin format for convenience and testing purposes. I am still aiming to submit it as a patch to Rails 2.0. I’d appreciate any feedback!
get it here:
svn export --username=public svn://internautdesign.com/public/plugins/friendly_fixtures vendor/plugins/friendly_fixtures
UPDATE: now available at github: http://github.com/dfl/friendly_fixtures/tree/master
from the README:
FriendlyFixtures
This plugin is a simple extension to add some cool features to the fixtures macro in Test::Unit. It is intended for Rails 2.0, but works with 1.2.3 as well.
It enables you to:- load dependent models, which are found by object introspection on a model’s ActiveRecord associations.
- assert that all the loaded fixtures are valid. This can be very helpful in finding bugs.
Example Usage:
class SomeTest < Test::Unit::TestCase
fixtures :user, :dependencies => true, :validate => true
end
I recently wrote a functional test for an AJAX callback action. I wanted to assert that the RJS replaced some text with a particular string. This string is generated by a view helper. To keep this flexibility, I wanted to call the helper from the test.
It turns out to be quite simple. All you have to do is mix-in the helper to your TestCase class, like so:
class CompanyControllerTest < Test::Rails::TestCase
include CompanyHelper
...
end
In a previous post, I mentioned Gabriel Gironda’s snippet showing how to use view helpers in a controller. Calling view-specific helpers from the controller is a particularly useful technique in AJAX callback methods where you need to replace some HTML. The alternative is rendering a partial, which I felt was cumbersome and overkill if you just need to replace a single string of text.
However, the above technique doesn’t work out of the box if you need to use a custom helper that you have written in your app/helpers directory tree. The trick is to use the extend method to mix-in your custom helper modules.
Here is an example, where I extend the help singleton object with the CompanyHelper module, in order to be able to the text_for_action and text_for_notice methods.
def ajax_add_to_portfolio
help.extend ::CompanyHelper
raise "Company doesn't exist!" unless @company
kind = params[:category]
raise help.text_for_action( kind )+" already performed!" if @company.in_portfolio?( @current_user, kind )
@current_user.portfolio_items.create!( :company_id => params[:id], :category => kind )
action_text = help.text_for_action( kind, :past_tense => true )
notice_text = help.text_for_notice( kind )
render :update do |page|
page.flash_then_fade :success, action_text
page.replace_html kind, notice_text
end
rescue Exception => e
handle_exception e
end
this replaces my earlier post about testing for valid fixtures. Rails 2.0 patch coming soon…?
UPDATE: This monkey patch has been replaced by a plugin (with tests!): friendly_fixtures.
Rathole, a fixtures plugin so sweet it’s been incorporated into edge rails, is great—but unfortunately it doesn’t support polymorphic associations. That is, until now! :)
Get the patch: here.
UPDATE: I learned that the author, John Burnette, has renamed the project to foxy fixtures. He also massaged my patch into a contribution for rails 2.0: Ticket 10183.
There is some discussion that this patch is not necessary.
This morning I just discovered Shoulda, a really sweet testing framework that gives context and behavior without the whizz-bang syntax of RSpec and test-spec. Check it out!
My only complaints so far:
- the example code on their homepage is missing “do” keywords after some of the “should” statements. oops!
- I can no longer run an individual test in textmate with APPLE-shift-R, as there is no literal method to run, just a block. Hopefully this will be fixed with a forthcoming shoulda textmate bundle.
Have you ever wanted to render a partial to a string from inside a model?
This solution was inspired by this snippet showing how to use view helpers in a controller. It’s clean and simple, no need to mess with ERB or metaprogramming!
class Model
class Helper < ActionView::Base
include Singleton
end
def help
Helper.instance
end
...
def summarize
## Note that we have to use the FULL path here!
help.render( :partial => "#{RAILS_ROOT}/app/views/notifications/text_order_summary", :object => self )
end
alias_method :to_s, :summarize
end
Have you ever wanted to refactor something into the model ( skinny controller, fat model ) but didn’t know how to deal with your flash notifications?
Here’s a solution that I cooked up:
module FlashExceptions
class FlashException < StandardError; end
class FlashError < FlashException; end
class FlashNotice < FlashException; end
class FlashSuccess < FlashException; end
end
###########################################
class Model < ActiveRecord::Base
include FlashExceptions
def self.do_something! opts = {}
raise FlashError, opts[:error] if opts[:error]
raise FlashNotice, opts[:notice] if opts[:notice]
raise FlashSuccess, opts[:success] if opts[:success]
end
end
###########################################
class Controller < ApplicationController
def action
Model.do_something! :error => 'oops!', :notice => 'ahem.', :success => 'yay!'
rescue FlashException => e
flash[ e.class.underscore.split('_').last ] = e.message
end
end
I wrote a previous entry about a pattern for making CSS rules specific to controllers and actions.
Unfortunately this didn’t work in IE. Here is an alternative solution, which is cross-browser compatible:
<body id="<%= controller.controller_name %>" class="action-<%= controller.action_name %>">
(I chose to prefix the action name with action, to avoid any potential namespace contamination )
Here are the new CSS rules:
body#register {} /* all actions in controller */
body#register.action-step_1 {} /* only step_1 action */
I wrote these test_helper methods after being inspired by Zack Chandler’s assert_toggled method
def assert_incremented_by( number, object, method, *args )
initial_value = object.send(method, *args)
yield
object.reload if object.respond_to? :reload
assert_equal initial_value + number, object.send(method, *args)
end
def assert_decremented_by( number, object, method, *args, &block )
assert_incremented_by -number, object, method, *args, &block
end
def assert_no_change_in( object, method, *args )
initial_value = object.send(method, *args)
yield
object.reload if object.respond_to? :reload
assert_equal initial_value, object.send(method, *args)
end
example usage:
def test_ajax_create_network__for_city_is_successful_and_updates_form_id_value
assert_incremented_by 1, City, :count do
xhr :post, :ajax_create_network, :type => 'City', :object => { :name => 'Dummy', :state => 'CA' }
end
assert_response :success
assert_match /\.value='\d+'/, @response.body
end
...
def test_after_create__watchlist_notification_on_posting
assert users(:david).watchlist_companies.include?( companies(:HP) )
assert_incremented_by 1, WatchlistNotification, :count, :conditions => {:kind => 'posting_commented'} do
postings(:rodney_HP).comments.create!( :body => 'booyashaka!', :user => users(:greg) )
end
end
def test_after_create__watchlist_notification__doesnt_happen_on_profile
assert users(:david).watchlist_companies.include?( companies(:HP) )
assert_no_change_in WatchlistNotification, :count do
users(:rodney).profile.comments.create!( :body => 'booyashaka!', :user => users(:greg) )
end
end
put this in your test_helper.rb
def test_all_models_valid model
objs = model.camelize.constantize.find(:all)
objs.each do |obj|
assert obj.valid?, "#{model} #{obj.id} is invalid: #{obj.errors.full_messages.join(', ')}"
end
end
def test_all_models_valid! filename
test_all_models_valid klass = filename.split('/').last.sub(/_test.rb/,'').camelize
end
Now you can create a test like this in each of your your model/unit tests:
def test_valid_fixtures
test_all_models_valid! __FILE__
end
Sweet! :)
Update #1: Thanks to Nicolas Sanguinetti for the tip on how to avoid the use of eval.
I’ve been using this a lot in one of our current projects.. it comes in pretty handy. just create a
<div id="message" style="display: none"></div> in your view.
Here is an example from our login page:
# this goes in your application_helper.rb
# call it from your layout like this:
# <%= flash_for :error %>
# <%= flash_for :notice %>
# <%= flash_for :success %>
def flash_for symbol
# <div id="flash_error" class="message-block error">
# text
# </div>
content_tag( :div, flash[symbol].to_s, :id => "flash_#{symbol}", :class => "message-block #{symbol}",
:style => flash[symbol] ? nil : 'display: none' )
end
# this goes in your controller
def login #http get, ajax post
redirect_to home_url( current_user ) and return if user_logged_in? #already logged in?
if request.xhr?
raise "Please enter a valid email address." unless params[:user][:email] =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
raise "Please enter a password!" if params[:user][:password].blank?
if user = User.authenticate( params[:user][:email], params[:user][:password] )
::ActionController::Base.session_options[:session_expires] = params[:user][:remember] ? 2.weeks.from_now : nil # remember me for 2 weeks if checked
login_user user
ajax_redirect_to home_url(current_user)
else
session[:forgotten_email] = params[:user][:email]
raise "Incorrect email address or password."
end
end
rescue Exception => e
handle_ajax_error e
end
# this goes in application.rb
protected
def ajax_redirect_to url
url = url_for( url ) if url.is_a? Hash
render :update do |page|
page << "window.location = '#{url}'"
end
end
def handle_ajax_error e
render :update do |page|
page.flash_then_fade :error, "Error: <nobr>#{e.message}</nobr>"
page << "Element.scrollTo('flash_error');"
end
logger.error "\n\n#{e.message}"
logger.info e.backtrace.join("\n")
end
# this goes in /lib directory in a file that gets loaded in environment.rb
module ActionView
module Helpers
module PrototypeHelper
class JavaScriptGenerator
module GeneratorMethods
def flash_then_fade symbol, message, seconds=0, fadeout=1
# update message text
replace_html "flash_#{symbol}", message
# hide all notices except current
(%w[ error success notice ] - [ symbol.to_s ]).each do |sym|
hide "flash_#{sym}"
end
dom_id = "flash_#{symbol}"
visual_effect :highlight, dom_id, :duration => 2.0
show dom_id
if seconds.to_f > 0
delay( seconds ) do
visual_effect :fade, dom_id, :duration => fadeout
end
end
end
end
end
end
end
end
def initialize *args
ajax_actions = self.public_methods(false).grep(/^ajax/i)
unless ajax_actions.empty?
self.class.send :eval, <<-RUBY
verify :xhr => true,
:only => [#{ajax_actions.map(&:to_sym).join(', ')}],
:render => {:text => '405 XHR only', :status => 405 }
RUBY
end
super *args
end

