How to share methods between ActionMailers - ruby-on-rails-3.1

I have two mailers:
class Mailer1 < ActionMailer::Base
def mail
if check_something?
end
end
private
def check_something?
end
end
class Mailer2 < ActionMailer::Base
def another_mail
if check_something?
end
end
private
def check_something?
end
end
(I understand I can pull in view helpers for the actual mail templates, but how can I make it work for controller-type "helper" methods - as ActionMailers derive from Abstract Controller these days.)
So, where can I declare check_something?, and how can I make it accessible to both my mailers?

Just create a base class, like you get by default with ApplicationController for your http controllers:
class AppMailer < ActionMailer::Base
protected
def check_something?
end
end
class Mailer1 < AppMailer
def mail
if check_something?
end
end
end
class Mailer2 < AppMailer
def another_mail
if check_something?
end
end
end

Related

FactoryMethod pattern on Ruby

I'm learning the design patterns. How do you think is it an appropriate example of FactoryMethod pattern?
There are Unit and its subclasses: Soldier and Doctor. They can greet somehow. There are also UnitFactory, SoldierFactory and DoctorFactory. They produce according units.
class Unit
class GreetError < StandardError; end
def greet; raise GreetError; end
end
class Soldier < Unit
def greet; 'I am a soldier'; end
end
class Doctor < Unit
def greet; 'I am a doctor'; end
end
class UnitFactory
class CreateUnitError < StandardError; end
def create_unit; raise CreateUnitError; end
end
class SoldierFactory < UnitFactory
def create_unit; Soldier.new; end
end
class DoctorFactory < UnitFactory
def create_unit; Doctor.new; end
end
class Army
attr_reader :unit_factory, :count, :units
def initialize(unit_factory, count)
#unit_factory = unit_factory
#count = count
#units = []
gather
end
def gather
count.times { units << unit_factory.create_unit }
end
def greet
units.map { |unit| unit.greet }
end
end

Define protected class methods from module - ruby

I'm trying to give a class a protected method via modules which can only be called by itself and other classes inheriting them. I'd like to hide the method from being used by Class.method and only be accessible to the Class class internally or subclasses that inherit Class. How would I go about doing this? This is what I have so far.
#! /usr/bin/env ruby
module ProtectedClassMethods
#class_instance_var = 1234567
def included(base); base.extend(ProtectedClassMethods); end
protected
def protected_class_method; puts "A PROTECTED CLASS METHOD => #{#class_instance_var}"; end
end
class Class1
def value; "Class1"; end
end
class Class2 < Class1
extend ProtectedClassMethods
class << self
protected_class_method #crashes here
end
def value; "Class2"; end
end
class Class3 < Class2
class << self
#class_instance_var = 24681012
protected_class_method
end
def value; "Class3"; end
end
puts "Initializing Class1"
class1 = Class1.new
puts "Done (Class1)"
puts "Initializing Class2"
class2 = Class2.new
puts "Done (Class2)"
puts "Initializing Class3"
class3 = Class3.new
puts "Done (Class3)"
puts class1.value
puts class2.value
puts class3.value
gives this error
./protected_class_test.rb:20:in `singletonclass': undefined local variable or method `protected_class_method' for #<Class:Class2> (NameError)
from ./protected_class_test.rb:18:in `<class:Class2>'
from ./protected_class_test.rb:16:in `<main>'
Here is a working thing.
module ProtectedClassMethods
#class_instance_var = 1234567
def included(base); base.extend(ProtectedClassMethods); end
protected
def protected_class_method; puts "A PROTECTED CLASS METHOD => #{#class_instance_var}"; end
end
class Class1
def value; "Class1"; end
end
class Class2 < Class1
extend ProtectedClassMethods
protected_class_method #crashes here
def value; "Class2"; end
end
class Class3 < Class2
#class_instance_var = 24681012
protected_class_method
def value; "Class3"; end
end
puts "Initializing Class1"
class1 = Class1.new
puts "Done (Class1)"
Doing
class << self
protected_class_method #crashes here
end
You were actually calling the method on the meta class (the class of the class) and the method was defined on the class itself.

Service objects pattern in Ruby on Rails

I´m trying to develop a service class that provides payment services in my Rails app, but it´s not working.
Service class (lib/paypal_service.rb) (not sure if it should be placed here, I read it in some posts):
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize()
#api = PayPal::SDK::Merchant::API.new
end
def test()
puts "Congratulations, you have called test"
end
end
Controller (uses service):
class BookingsController < ApplicationController
include BoatsHelper
require 'paypal_service'
def create
PaypalService.test
end
...
In output I get:
NoMethodError (private method `test' called for PaypalService:Class):
It's because you are calling a class method, but you have defined an instance method.
Change you controller to this
def create
PaypalService.new.test
end
Or define a class method and leave your controller as is
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize()
#api = PayPal::SDK::Merchant::API.new
end
def self.test
new.test
end
def test()
puts "Congratulations, you have called test"
end
end
Use PaypalService.new.test instead of PaypalService.test as test is an instance method of class PaypalService and not a class method. Update it as below:
class BookingsController < ApplicationController
include BoatsHelper
require 'paypal_service'
def create
PaypalService.new.test
end
...
NOTE:
If you want to call it as PaypalService.test then you can convert test to a class method as follows:
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize
#api = PayPal::SDK::Merchant::API.new
end
def self.test
puts "Congratulations, you have called test"
end
end

Rails - how to call methods from lib directory?

I have this method in the lib dir (file my_class_name.rb):
class MyClassName
def doSomething
...
end
...
end
in the controller:
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
::MyClassName.doSomething()
end
end
returns
undefined method `doSomething' for MyClassName:Class
How to properly call this method?
You've written a class with an instance method, so if you want to call it how you've written it you'll need to write:
mcn = MyClassName.new
mcn.doSomething
(by creating an instance, and then calling the method on that instance)
If what you want is a class method, define it as:
class MyClassName
def self.doSomething
...
end
...
end
and call it like: MyClassName.doSomething
class MyClassName
def self.doSomething
...
end
...
end
You have made and instance method not class method, change your code as follow, plus i would suggest you instead of making it as a class make it a module and include in your model and call doSomething from model.
class MyClassName
def self.doSomething
...
end
...
end
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
MyClassName.doSomething()
end
end
If you are looking to make it work as is (with tiny change) then you should create an instance of MyClassName e.g. ::MyClassName.new.doSomething()
class MyClassName
def doSomething
...
end
...
end
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
::MyClassName.new.doSomething()
end
end

How to set just one method to private in Ruby?

I have a class with N methods. I want to set one of these methods to private. How can I do this?
class Example
def methodA
end
def methodP
end
private :methodP
end
I like this way:
class Example
def public_method1
end
private def used_by_public_method1
end
def public_method2
end
end
Another option (that I find more confusing):
class Example
def public_method1
end
def public_method2
end
private
def used_by_public_method1
end
# Don't accidentally put public methods down here.
end

Resources