rmcsharry
rmcsharry

Reputation: 5562

What is the 'end.new' in Ruby for? Why not just use 'end' on it's own

I came across this question and the answer from @Kris has the line:

end.new

here:

  subject do
    Class.new do
      include ActiveModel::Validations    
      attr_accessor :email
      validates :email, email: true
    end.new
  end

I have not seen that before and cannot find other examples nor explanations.

Why not just 'end' on it's own, like this:

  subject do
    Class.new do
      include ActiveModel::Validations    
      attr_accessor :email
      validates :email, email: true
    end
  end

What is the difference?

Upvotes: 1

Views: 118

Answers (1)

max pleaner
max pleaner

Reputation: 26778

First of all you need to understand that you can chain statements on end, for example

[1,2,3,4,5].select do |num|
  i % 2 == 0
end.map do |num|
  "#{num} is even"
end.each do |str|
  puts str
end

Next, to understand your example you need to understand what is an "anonymous" class.

You can define this class normally instead:

class MyClass
  include ActiveModel::Validations    
  attr_accessor :email
  validates :email, email: true
end

and you will have defined a global MyClass variable that refers to the class. Of course, you can call MyClass.new to get an instance.

The anomymous class block Class.new do is the same thing but it doesn't define a global identifer for the class. Instead, to get a handle on the class you must assign a variable to the result of the Class.new do .. end expression.

So, if you understand that Class.new do ... end returns a class, and you can call .new on any class, then you can do something like the code in your question:

klass = Class.new { def foo; "bar"; end }
klass.new.foo # => "bar"

# or ...
Class.new { def foo; "bar"; end }.new.foo # => "bar"

do ... end being the multiline version of {} to define a block

Upvotes: 3

Related Questions