NullVoxPopuli
NullVoxPopuli

Reputation: 65103

Ruby on Rails: Is it possible to extend a method without overriding it?

I want to change the redirect on a create method, but I don't want to override the whole thing.

like, by default, if create (lets say) exists, it will have something like

  respond_to do |format|
      if @user.save(params[:user])
        flash[:notice] = 'The user has been updated'
        format.html { redirect_to :controller => "subscriptions",
                                  :action => "show",
                                  :id => @user.account_id }
        format.xml { head :ok }
      else
        format.html { render :action => :edit }
            format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
        end
    end

or something like that...

but where it says format.html... I want to be able to change the redirect_to in my class that inherits this method... but I don't want to rewrite the whole thing. =\

ideas?

Upvotes: 0

Views: 207

Answers (2)

Faisal
Faisal

Reputation: 18978

Calling super won't solve your problem, because you want to alter the inner workings of the method, not pass new parameters or add code to it.

What I would do, is create a third function (lets call it common_routine) that has the common functionality. Then you would call common_routine from both places that need to access it. However, to change the code as you need, you'll pass it a block, and yield that block inside the method to modify how the method works.

example:

def common_routine
  respond_to do |format|
    if @user.save(params[:user])
      flash[:notice] = 'The user has been updated'
      format.html { yield }
      format.xml { head :ok }
    else
      format.html { render :action => :edit }
      format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
    end
  end
end

Then you call it with:

common_routine { redirect_to :controller => "subscriptions", :action => "show", :id => @user.account_id }

or

common_routine { redirect_to root_path }

The code block that you pass to common_routine would be "yielded", which allows you to have the same functionality with minor tweaks as needed.

Upvotes: 1

Karl
Karl

Reputation: 6165

If you know what arguments the original method takes, you can call the super method.

class Foo
  def foo(arg)
    arg*2
  end
end

class Bar < Foo
  def foo(arg)
    super(arg) + 3
  end
end

a = new Foo
a.foo(2)     # => 4
b = new Bar
b.foo(2)     # => 7

Upvotes: 0

Related Questions