Skip_before_filter (Do I need a lesson in modules/mixins?)

Gurus,

I am reading the O'Reilly book "Rails: Up and Running, 2nd Edition" and
the author told me to add the following line of code:

skip_before_filter :verify_authenticity_token

as follows:

class SlidesController < ApplicationController
  skip_before_filter :verify_authenticity_token
  ...

This stopped me dead in my tracks as I realized I had no idea what was
going on. I am using Aptana (Eclipse) and so it can tell me that
skip_before_filter is defined in the module ClassMethods. I am assuming
that somehow this method (skip_before_filter) is mixed in?

The implementation is:
      def skip_before_filter(*filters)
        filter_chain.skip_filter_in_chain(*filters, &:before?)
      end

What is *filters? Did I miss this in my 'Learning Ruby' book?

Anyway, I guessed that I was calling the method 'skip_before_filter'
sometime during my controller's construction. So I built a toy to
validate as follows:
####################BEGIN
test.rb###############################################
module Test
  def call_me
    puts "Mixin called"
  end
end
module Test2
  def call_me
    puts "second mixin called"
  end
end

class Tester
  include Test, Test2
  #call_me() #this call fails. This blows my theory...

  def initialize
    super
    call_me()# this call works, but how would I call the other one?
    #Test2::call_me()#this call fails
    puts "A tester was built"
  end

end

Tester.new
########################################END test.rb###########

output is:
Mixin called
A tester was built

Thanks for your help with my questions.

Cris

···

--
Posted via http://www.ruby-forum.com/.

this is a ruby mailing list, not a ruby on rails mailing list. Please post in the appropriate area.

···

On Aug 12, 2009, at 14:50 , Cris Shupp wrote:

I am reading the O'Reilly book "Rails: Up and Running, 2nd Edition" and

Gurus,

I am reading the O'Reilly book "Rails: Up and Running, 2nd Edition" and
the author told me to add the following line of code:

skip_before_filter :verify_authenticity_token

as follows:

class SlidesController < ApplicationController
skip_before_filter :verify_authenticity_token
...

This stopped me dead in my tracks as I realized I had no idea what was
going on. I am using Aptana (Eclipse) and so it can tell me that
skip_before_filter is defined in the module ClassMethods. I am assuming
that somehow this method (skip_before_filter) is mixed in?

The implementation is:
def skip_before_filter(*filters)
filter_chain.skip_filter_in_chain(*filters, &:before?)
end

What is *filters? Did I miss this in my 'Learning Ruby' book?

This collects all of the arguments into an array called filters. You
can find more looking for "ruby splat" on google.

Anyway, I guessed that I was calling the method 'skip_before_filter'
sometime during my controller's construction. So I built a toy to
validate as follows:
####################BEGIN
test.rb###############################################
module Test
def call_me
puts "Mixin called"
end
end
module Test2
def call_me
puts "second mixin called"
end
end

class Tester
include Test, Test2
#call_me() #this call fails. This blows my theory...

def initialize
super
call_me()# this call works, but how would I call the other one?
#Test2::call_me()#this call fails
puts "A tester was built"
end

end

Tester.new
########################################END test.rb###########

output is:
Mixin called
A tester was built

Rails uses a convention with modules similar to the following:

module FooBehaviors
  def self.included(base)
    base.extend(ClassMethods)
  end
  module ClassMethods
    def foo
      puts 42
    end
  end
end

class Bar
  include FooBehaviors
  foo
end

When FooBehaviors module is included, it also extends the including
class with the FooBehaviors::ClassMethods module. You can find out
more by looking at the differences between include and extend.

http://railstips.org/2009/5/15/include-verse-extend-in-ruby

Best,
Michael Guterl

···

On Wed, Aug 12, 2009 at 5:50 PM, Cris Shupp<cshupp1@yahoo.com> wrote:

Cris Shupp wrote:

What is *filters? Did I miss this in my 'Learning Ruby' book?

def meth1(*args)
  p args
end

meth1(1, 2, 3)

--output:--
[1, 2, 3]

def meth2(x, y, z)
  puts x, y, z
end

args = [1, 2, 3]
meth2(*args)

--output:--
1
2
3

def meth3(x, y, *args)
  p x, y, args
end

meth3(1, 2, 3, 4, 5, 6)

--output:--
1
2
[3, 4, 5, 6]

···

--
Posted via http://www.ruby-forum.com/\.

He asked a Ruby question, using Rails code as an example. Please don't be unfriendly.

···

On Thu, 13 Aug 2009 09:02:30 +0900, Ryan Davis wrote:

On Aug 12, 2009, at 14:50 , Cris Shupp wrote:

I am reading the O'Reilly book "Rails: Up and Running, 2nd Edition" and

this is a ruby mailing list, not a ruby on rails mailing list. Please
post in the appropriate area.

When FooBehaviors module is included, it also extends the including
class with the FooBehaviors::ClassMethods module. You can find out
more by looking at the differences between include and extend.

http://railstips.org/2009/5/15/include-verse-extend-in-ruby

Best,
Michael Guterl

Michael,

Thanks for your response. Your url was helpful and by following the
inheritance tree I found the code that includes skip_before_filter:

  Base.class_eval do
    [ Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds,
Helpers,
      Cookies, Caching, Verification, Streaming, SessionManagement,
      HttpAuthentication::Basic::ControllerMethods,
HttpAuthentication::Digest::ControllerMethods,
      RecordIdentifier, RequestForgeryProtection, Translation
    ].each do |mod|
      include mod
    end

but I still feel like skip_before_filter is a dangling method call in
the following code:

class SlidesController < ApplicationController
  skip_before_filter :verify_authenticity_token

I tried creating a simple example (using what your url illustrated) but
it does not work. Here is my toy The first 'call_me' invocation is
what I am assuming is equivalent to the skip_before_filter call:

module Test

  def self.include(base)
    base.extend(ClassMethods)
  end

  module ClassMethods

    def call_me
      puts "Class method"
    end
  end
end

module Test2
  def call_me
    puts "second mixin called"
  end
end

class Tester
  include Test, Test2
  call_me()#toy.rb:23: undefined method `call_me' for Tester:Class
(NoMethodError)

  def initialize
    super
    call_me()
    puts "A tester was built"
  end

end

Tester.new

I should mention that I am seeing these 'dangling' calls more and more
as I look through what the scaffolding generated so I would like a clue!

Thanks,

Cris

···

--
Posted via http://www.ruby-forum.com/\.

def self.included(base)

irb(main):016:0> module Test
irb(main):017:1>
irb(main):018:1* def self.included(base)
irb(main):019:2> base.extend(ClassMethods)
irb(main):020:2> end
irb(main):021:1> module ClassMethods
irb(main):022:2> def call_me
irb(main):023:3> puts "Class method"
irb(main):024:3> end
irb(main):025:2> end
irb(main):026:1> end
=> nil
irb(main):027:0> class Tester
irb(main):028:1> include Test
irb(main):029:1> call_me
irb(main):030:1> end
Class method
=> nil

Hope this helps,

Jesus.

···

On Thu, Aug 13, 2009 at 4:19 PM, Cris Shupp<cshupp1@yahoo.com> wrote:

I tried creating a simple example (using what your url illustrated) but
it does not work. Here is my toy The first 'call_me' invocation is
what I am assuming is equivalent to the skip_before_filter call:

module Test

def self.include(base)

Is it the fact that the method calls aren't happening within another
method tripping you up? In Ruby, most everything happens at runtime,
class creation included. Also, everything's an object. So when
something like

class Foo; some_ish; end

happens, Ruby is creating a new class, and some_ish is just being run
in the instance of the Class that is being created. (well it *is* more
complicated than that, but that should be enough to help understand
whats going on?). Its really no different than attr_accessor and
friends.

···

On Aug 13, 10:19 am, Cris Shupp <cshu...@yahoo.com> wrote:

I should mention that I am seeing these 'dangling' calls more and more
as I look through what the scaffolding generated so I would like a clue!

Thanks,

Cris
--
Posted viahttp://www.ruby-forum.com/.

Well I can reproduce that in irb, but no it doesn't answer my question.

Anyone out there know the answer?

Thanks,

Cris

Jesús Gabriel y Galán wrote:

···

On Thu, Aug 13, 2009 at 4:19 PM, Cris Shupp<cshupp1@yahoo.com> wrote:

I tried creating a simple example (using what your url illustrated) but
it does not work. �Here is my toy �The first 'call_me' invocation is
what I am assuming is equivalent to the skip_before_filter call:

module Test

�def self.include(base)

def self.included(base)

irb(main):016:0> module Test
irb(main):017:1>
irb(main):018:1* def self.included(base)
irb(main):019:2> base.extend(ClassMethods)
irb(main):020:2> end
irb(main):021:1> module ClassMethods
irb(main):022:2> def call_me
irb(main):023:3> puts "Class method"
irb(main):024:3> end
irb(main):025:2> end
irb(main):026:1> end
=> nil
irb(main):027:0> class Tester
irb(main):028:1> include Test
irb(main):029:1> call_me
irb(main):030:1> end
Class method
=> nil

Hope this helps,

Jesus.

--
Posted via http://www.ruby-forum.com/\.

No it is not the fact that the method call is not within another method
call that is tripping me up. It is that I cannot get it to work for me.

Consider the following code:

···

####################################
module Test

  def self.include(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def call_me
      puts "Class method"
    end
  end
end

class Tester
  include Test
call_me#toy.rb:23: undefined method `call_me' for
Tester:Class(NoMethodError)
end

Tester.new
###################################

yields the following results:
toy.rb:24: undefined local variable or method `call_me' for Tester:Class
(NameError)

Again I am assuming my 'call_me' is equivalent to my originally
referenced 'skip_before_filter'.

Thanks,

Cris

pharrington wrote:

On Aug 13, 10:19�am, Cris Shupp <cshu...@yahoo.com> wrote:

I should mention that I am seeing these 'dangling' calls more and more
as I look through what the scaffolding generated so I would like a clue!

Thanks,

Cris
--
Posted viahttp://www.ruby-forum.com/.

Is it the fact that the method calls aren't happening within another
method tripping you up? In Ruby, most everything happens at runtime,
class creation included. Also, everything's an object. So when
something like

class Foo; some_ish; end

happens, Ruby is creating a new class, and some_ish is just being run
in the instance of the Class that is being created. (well it *is* more
complicated than that, but that should be enough to help understand
whats going on?). Its really no different than attr_accessor and
friends.

--
Posted via http://www.ruby-forum.com/\.

You have the same typo: it's self.included (note the final 'd').

Jesus.

···

On Thu, Aug 13, 2009 at 8:40 PM, Cris Shupp<cshupp1@yahoo.com> wrote:

No it is not the fact that the method call is not within another method
call that is tripping me up. It is that I cannot get it to work for me.

Consider the following code:
####################################
module Test

def self.include(base)
base.extend(ClassMethods)
end

No it is not the fact that the method call is not within another method
call that is tripping me up. It is that I cannot get it to work for me.

Consider the following code:
####################################
module Test

def self.include(base)
base.extend(ClassMethods)
end

module ClassMethods
def call_me
puts "Class method"
end
end
end

class Tester
include Test
call_me#toy.rb:23: undefined method `call_me' for
Tester:Class(NoMethodError)
end

Tester.new
###################################

yields the following results:
toy.rb:24: undefined local variable or method `call_me' for Tester:Class
(NameError)

Again I am assuming my 'call_me' is equivalent to my originally
referenced 'skip_before_filter'.

Thanks,

Cris

Then I'm confused as to what you're still confused about? Jesus
already pointed out the typo: you need

def self.included(base)

versus

···

On Aug 13, 2:40 pm, Cris Shupp <cshu...@yahoo.com> wrote:

def self.include(base)

Thanks everyone (especially Michael and Jesus)!

I missed the missing 'd'. I put it in and it works!

And of course the 'd' is in the original code...

module ActionController #:nodoc:
  module Filters #:nodoc:
    def self.included(base)
      base.class_eval do
        extend ClassMethods
        include ActionController::Filters::InstanceMethods
      end
    end

pharrington wrote:

···

On Aug 13, 2:40�pm, Cris Shupp <cshu...@yahoo.com> wrote:

Tester:Class(NoMethodError)
referenced 'skip_before_filter'.

Thanks,

Cris

Then I'm confused as to what you're still confused about? Jesus
already pointed out the typo: you need

def self.included(base)

versus

--
Posted via http://www.ruby-forum.com/\.