Should I prefer instance methods over class methods in Ruby?

I’m working on a rails application, and I’ve been pulling functionality out of my rails code and into pure ruby classes in lib/. I’ve found myself often writing classes like this:

 class MailchimpIntegration   
  def subscribe_email(email, fname, lname)
    Gibbon.list_subscribe(:id => NEWSLETTER_LIST_ID, :email_address => email,
      :merge_vars => {'fname' => fname, 'lname' => lname },
      :email_type => "html",  :double_optin => false, :send_welcome => false)
  end

  def unsubscribe_email(email)
    Gibbon.list_unsubscribe(:id => NEWSLETTER_LIST_ID, :email_address => email)
  end

  def change_details(old_email, email, fname, lname)
    Gibbon.list_update_member(:id => NEWSLETTER_LIST_ID, :email_address => old_email,
      :merge_vars => {'email' => email, 'fname' => fname, 'lname' => lname })
  end

  def get_email_info(email)
    Gibbon.list_member_info(:id => NEWSLETTER_LIST_ID, :email_address => [email])["data"].first
  end
end

My question is: Should I change these methods to be class methods?

It seems reasonable to do, as I’ll probably end up calling these by just newing up a MailchimpIntegration class each time. However, I generally prefer to have instance methods as they can be more easily stubbed etc, although this seems to be less of an issue in ruby.

I have several classes like this in my system, so I’d be keen to see what people think about this.

1

Another approach you can take is to use mixins.

    module InteractsWithMailChimp
       def subscribe_email(email, fname, lname)
          Gibbon.list_subscribe(:id => NEWSLETTER_LIST_ID, :email_address => email, 
          :merge_vars => {'fname' => fname, 'lname' => lname }, 
          :email_type => "html",  :double_optin => false, :send_welcome => false)
       end
    end

    Class User
        include InteractsWithMailChimp
    end

This approach would give you the benefit of having/using instance variables from the context of the user within the module. The module can be tested in isolation by extending it within any test case. Within the module you can separate the responsibilities for example you can consider that the subscribe/unsubcribe part is a responsibility on its own so you would have:

    module InteractsWithMailChimp
       class HandlesSubscriptions
           def subscribe_email(email, fname, lname)
              Gibbon.list_subscribe(:id => NEWSLETTER_LIST_ID, :email_address => email, 
              :merge_vars => {'fname' => fname, 'lname' => lname }, 
              :email_type => "html",  :double_optin => false, :send_welcome => false)
           end
       end
    end

    Class User
        include InteractsWithMailChimp::HandlesSubscriptions
    end

Within classes that are part of the module if you consider that you would not need any external data there is no problem of making the methods class ones. I like the mixin approach more because it’s simple to reuse, it does not need to repeat yourself with the object instantiation and I can name my modules and classes within modules referring exactly to the responsibility they have.
I would still keep these module separate in /lib of course.
For more really nice tips and tricks on how to organize your rails code and have your test run fast you can check out fast rails tests. Hope it helps.

I’m putting this in as an answer, since I could be wrong, but I think I have a good reason for going with instance methods as opposed to class methods in this case.

The mailchimp class above is called from the User class when the user is saved, email edited, etc, realized that I need to make sure I don’t call the mailchimp API in test, or all my tests will be super slow. (I stub out the mailchimp stuff in the tests dealing with that, but I don’t for the other tests which just deal with user).

With class methods, this seems like it would be a pain since I can’t easily stub out all the methods, but with MailchimpIntegration objects, I can just put:

  def mailchimp
    if Rails.env.production?
      MailchimpIntegration.new
    else
      NullObject.new
    end
  end

In my user class, and stub that out to return my stub object with I’m testing the integration.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật