#
# Copyright (c) 2006-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# This file is part of Ronin.
#
# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ronin. If not, see .
#
require 'ronin/model'
require 'ronin/model/has_unique_name'
require 'ronin/model/has_description'
require 'ronin/address'
require 'ronin/target'
require 'dm-timestamps'
module Ronin
#
# Represents a grouping of targeted {Address}es.
#
class Campaign
include Model
include Model::HasUniqueName
include Model::HasDescription
# Primary key of the campaign
property :id, Serial
# Defines the `created_at` and `updated_at` timestamps
timestamps :at
# The targets of the campaign
has 0..n, :targets
# The addresses being targeted in the campaign
has 0..n, :addresses, :through => :targets
# The organization the campaign covers
has 0..n, :organizations, :through => :targets
#
# Searches for all campaigns targeting an {Address}.
#
# @param [Array, String] addr
# The address(es) to search for.
#
# @return [Array]
# The campaigns that target the given address.
#
# @since 1.0.0
#
# @api public
#
def self.targeting(addr)
all('addresses.address' => addr)
end
#
# Searches for all campaigns targeting an {Organization}.
#
# @param [Array, String] names
# The organization name(s) to search for.
#
# @return [Array]
# The campaigns that target the specified organizations.
#
# @since 1.0.0
#
# @api public
#
def self.targeting_orgs(names)
all('organizations.name' => names)
end
#
# Determines if an address is targeted by the campaign.
#
# @param [Address] address
# The address.
#
# @return [Boolean]
# Specifies whether the address is targeted.
#
# @since 1.0.0
#
# @api public
#
def targets?(address)
self.addresses.include?(address)
end
#
# Adds an address to the campaign.
#
# @param [String] addr
# The address that will be targeted.
#
# @return [Target]
# The new target of the campaign.
#
# @raise [RuntimeError]
# The given address could not be found.
#
# @since 1.0.0
#
# @api public
#
def target!(addr)
unless (address = Address.first(:address => addr))
raise("unknown address #{addr.dump}")
end
return Target.first_or_create(:campaign => self, :address => address)
end
end
end