Class: DevDNSd::Rule

Inherits:
Object
  • Object
show all
Includes:
Lazier::I18n
Defined in:
lib/devdnsd/rule.rb

Overview

This class encapsulate a rule for matching an hostname.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block) ⇒ Rule

Creates a new rule.

Parameters:

  • match (String|Regexp) (defaults to: /.+/)

    The pattern to match.

  • reply (String) (defaults to: "127.0.0.1")

    The IP or hostname to reply back to the client.

  • type (Symbol) (defaults to: :A)

    The type of request to match.

  • options (Hash) (defaults to: {})

    A list of options for the request.

  • block (Proc)

    An optional block to compute the reply instead of using the reply parameter.

See Also:



37
38
39
40
41
42
# File 'lib/devdnsd/rule.rb', line 37

def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
  i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
  self.i18n = options[:locale]
  setup(match, reply, type, options, block)
  validate_rule
end

Instance Attribute Details

#blockProc

Returns An optional block to compute the reply instead of using the reply parameter. @see .create.

Returns:

  • (Proc)

    An optional block to compute the reply instead of using the reply parameter. @see .create



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/devdnsd/rule.rb', line 20

class Rule
  attr_accessor :match
  attr_accessor :type
  attr_accessor :reply
  attr_accessor :options
  attr_accessor :block

  include Lazier::I18n

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply [String] The IP or hostname to reply back to the client.
  # @param type [Symbol] The type of request to match.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
  # @see .create
  def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
    i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
    self.i18n = options[:locale]
    setup(match, reply, type, options, block)
    validate_rule
  end

  # Returns the resource class(es) for the current rule.
  #
  # @return [Array|Class] The class(es) for the current rule.
  def resource_class
    classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
    classes.length == 1 ? classes.first : classes
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
  def is_regexp?
    @match.is_a?(::Regexp)
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule has a block, `false` otherwise.
  def has_block?
    @block.present?
  end

  # Matches a hostname to the rule.
  #
  # @param hostname [String] The hostname to match.
  # @return [MatchData|Boolean|Nil] Return `true` or MatchData (if the pattern is a regexp) if the rule matches, `false` or `nil` otherwise.
  def match_host(hostname)
    is_regexp? ? @match.match(hostname) : (@match == hostname)
  end

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
  # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
  # @return [Rule] The new rule.
  def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
    validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
    setup(new(match), reply_or_type, type, options, block)
  end

  # Converts a class to the correspondent symbol.
  #
  # @param klass [Class] The class to convert.
  # @return [Symbol] The symbol representation of the class.
  def self.resource_class_to_symbol(klass)
    klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
  end

  # Converts a symbol to the correspondent DNS resource class.
  #
  # @param symbol [Symbol] The symbol to convert.
  # @param locale [Symbol] The locale to use for the messages.
  # @return [Symbol] The class associated to the symbol.
  def self.symbol_to_resource_class(symbol, locale = nil)
    symbol = symbol.to_s.upcase

    begin
      "Resolv::DNS::Resource::IN::#{symbol}".constantize
    rescue ::NameError
      raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
    end
  end

  private
    # Setups a new rule.
    #
    # @param match [String|Regexp] The pattern to match.
    # @param reply [String] The IP or hostname to reply back to the client.
    # @param type [Symbol] The type of request to match.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
    def setup(match, reply, type, options, block)
      @match = match
      @type = type || :A
      @reply = block.blank? ? (reply || "127.0.0.1") : nil
      @options = options
      @block = block
    end

    # Validates a newly created rule.
    def validate_rule
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_call)) if @reply.blank? && @block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_options)) if !@options.is_a?(::Hash)
    end

    # Setups a new rule.
    #
    # @param rv [Rule] The rule that is been created.
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @return [Rule] The new rule.
    def self.setup(rv, reply_or_type, type, options = {}, block)
      rv.options = options
      rv.block = block

      if block.present? then # reply_or_type acts like a type, type is ignored
        rv.type = reply_or_type || :A
        rv.reply = nil
      else # reply_or_type acts like a reply
        rv.reply = reply_or_type || "127.0.0.1"
        rv.type = type || :A
      end

      rv
    end

    # Validate options for a new rule creation.
    #
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @param localizer [Localizer] A localizer object.
    def self.validate_options(reply_or_type, options, block, localizer)
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_call)) if reply_or_type.blank? && block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_options)) if !options.is_a?(::Hash)
    end
end

#matchString|Regexp

Returns The pattern to match. Default: /.+/.

Returns:

  • (String|Regexp)

    The pattern to match. Default: /.+/.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/devdnsd/rule.rb', line 20

class Rule
  attr_accessor :match
  attr_accessor :type
  attr_accessor :reply
  attr_accessor :options
  attr_accessor :block

  include Lazier::I18n

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply [String] The IP or hostname to reply back to the client.
  # @param type [Symbol] The type of request to match.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
  # @see .create
  def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
    i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
    self.i18n = options[:locale]
    setup(match, reply, type, options, block)
    validate_rule
  end

  # Returns the resource class(es) for the current rule.
  #
  # @return [Array|Class] The class(es) for the current rule.
  def resource_class
    classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
    classes.length == 1 ? classes.first : classes
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
  def is_regexp?
    @match.is_a?(::Regexp)
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule has a block, `false` otherwise.
  def has_block?
    @block.present?
  end

  # Matches a hostname to the rule.
  #
  # @param hostname [String] The hostname to match.
  # @return [MatchData|Boolean|Nil] Return `true` or MatchData (if the pattern is a regexp) if the rule matches, `false` or `nil` otherwise.
  def match_host(hostname)
    is_regexp? ? @match.match(hostname) : (@match == hostname)
  end

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
  # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
  # @return [Rule] The new rule.
  def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
    validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
    setup(new(match), reply_or_type, type, options, block)
  end

  # Converts a class to the correspondent symbol.
  #
  # @param klass [Class] The class to convert.
  # @return [Symbol] The symbol representation of the class.
  def self.resource_class_to_symbol(klass)
    klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
  end

  # Converts a symbol to the correspondent DNS resource class.
  #
  # @param symbol [Symbol] The symbol to convert.
  # @param locale [Symbol] The locale to use for the messages.
  # @return [Symbol] The class associated to the symbol.
  def self.symbol_to_resource_class(symbol, locale = nil)
    symbol = symbol.to_s.upcase

    begin
      "Resolv::DNS::Resource::IN::#{symbol}".constantize
    rescue ::NameError
      raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
    end
  end

  private
    # Setups a new rule.
    #
    # @param match [String|Regexp] The pattern to match.
    # @param reply [String] The IP or hostname to reply back to the client.
    # @param type [Symbol] The type of request to match.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
    def setup(match, reply, type, options, block)
      @match = match
      @type = type || :A
      @reply = block.blank? ? (reply || "127.0.0.1") : nil
      @options = options
      @block = block
    end

    # Validates a newly created rule.
    def validate_rule
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_call)) if @reply.blank? && @block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_options)) if !@options.is_a?(::Hash)
    end

    # Setups a new rule.
    #
    # @param rv [Rule] The rule that is been created.
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @return [Rule] The new rule.
    def self.setup(rv, reply_or_type, type, options = {}, block)
      rv.options = options
      rv.block = block

      if block.present? then # reply_or_type acts like a type, type is ignored
        rv.type = reply_or_type || :A
        rv.reply = nil
      else # reply_or_type acts like a reply
        rv.reply = reply_or_type || "127.0.0.1"
        rv.type = type || :A
      end

      rv
    end

    # Validate options for a new rule creation.
    #
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @param localizer [Localizer] A localizer object.
    def self.validate_options(reply_or_type, options, block, localizer)
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_call)) if reply_or_type.blank? && block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_options)) if !options.is_a?(::Hash)
    end
end

#optionsHash

Returns A list of options for the request. Default is an empty hash.

Returns:

  • (Hash)

    A list of options for the request. Default is an empty hash.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/devdnsd/rule.rb', line 20

class Rule
  attr_accessor :match
  attr_accessor :type
  attr_accessor :reply
  attr_accessor :options
  attr_accessor :block

  include Lazier::I18n

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply [String] The IP or hostname to reply back to the client.
  # @param type [Symbol] The type of request to match.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
  # @see .create
  def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
    i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
    self.i18n = options[:locale]
    setup(match, reply, type, options, block)
    validate_rule
  end

  # Returns the resource class(es) for the current rule.
  #
  # @return [Array|Class] The class(es) for the current rule.
  def resource_class
    classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
    classes.length == 1 ? classes.first : classes
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
  def is_regexp?
    @match.is_a?(::Regexp)
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule has a block, `false` otherwise.
  def has_block?
    @block.present?
  end

  # Matches a hostname to the rule.
  #
  # @param hostname [String] The hostname to match.
  # @return [MatchData|Boolean|Nil] Return `true` or MatchData (if the pattern is a regexp) if the rule matches, `false` or `nil` otherwise.
  def match_host(hostname)
    is_regexp? ? @match.match(hostname) : (@match == hostname)
  end

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
  # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
  # @return [Rule] The new rule.
  def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
    validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
    setup(new(match), reply_or_type, type, options, block)
  end

  # Converts a class to the correspondent symbol.
  #
  # @param klass [Class] The class to convert.
  # @return [Symbol] The symbol representation of the class.
  def self.resource_class_to_symbol(klass)
    klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
  end

  # Converts a symbol to the correspondent DNS resource class.
  #
  # @param symbol [Symbol] The symbol to convert.
  # @param locale [Symbol] The locale to use for the messages.
  # @return [Symbol] The class associated to the symbol.
  def self.symbol_to_resource_class(symbol, locale = nil)
    symbol = symbol.to_s.upcase

    begin
      "Resolv::DNS::Resource::IN::#{symbol}".constantize
    rescue ::NameError
      raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
    end
  end

  private
    # Setups a new rule.
    #
    # @param match [String|Regexp] The pattern to match.
    # @param reply [String] The IP or hostname to reply back to the client.
    # @param type [Symbol] The type of request to match.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
    def setup(match, reply, type, options, block)
      @match = match
      @type = type || :A
      @reply = block.blank? ? (reply || "127.0.0.1") : nil
      @options = options
      @block = block
    end

    # Validates a newly created rule.
    def validate_rule
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_call)) if @reply.blank? && @block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_options)) if !@options.is_a?(::Hash)
    end

    # Setups a new rule.
    #
    # @param rv [Rule] The rule that is been created.
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @return [Rule] The new rule.
    def self.setup(rv, reply_or_type, type, options = {}, block)
      rv.options = options
      rv.block = block

      if block.present? then # reply_or_type acts like a type, type is ignored
        rv.type = reply_or_type || :A
        rv.reply = nil
      else # reply_or_type acts like a reply
        rv.reply = reply_or_type || "127.0.0.1"
        rv.type = type || :A
      end

      rv
    end

    # Validate options for a new rule creation.
    #
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @param localizer [Localizer] A localizer object.
    def self.validate_options(reply_or_type, options, block, localizer)
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_call)) if reply_or_type.blank? && block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_options)) if !options.is_a?(::Hash)
    end
end

#replyString

Returns The IP or hostname to reply back to the client. Default: 127.0.0.1. @see .create.

Returns:

  • (String)

    The IP or hostname to reply back to the client. Default: 127.0.0.1. @see .create



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/devdnsd/rule.rb', line 20

class Rule
  attr_accessor :match
  attr_accessor :type
  attr_accessor :reply
  attr_accessor :options
  attr_accessor :block

  include Lazier::I18n

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply [String] The IP or hostname to reply back to the client.
  # @param type [Symbol] The type of request to match.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
  # @see .create
  def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
    i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
    self.i18n = options[:locale]
    setup(match, reply, type, options, block)
    validate_rule
  end

  # Returns the resource class(es) for the current rule.
  #
  # @return [Array|Class] The class(es) for the current rule.
  def resource_class
    classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
    classes.length == 1 ? classes.first : classes
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
  def is_regexp?
    @match.is_a?(::Regexp)
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule has a block, `false` otherwise.
  def has_block?
    @block.present?
  end

  # Matches a hostname to the rule.
  #
  # @param hostname [String] The hostname to match.
  # @return [MatchData|Boolean|Nil] Return `true` or MatchData (if the pattern is a regexp) if the rule matches, `false` or `nil` otherwise.
  def match_host(hostname)
    is_regexp? ? @match.match(hostname) : (@match == hostname)
  end

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
  # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
  # @return [Rule] The new rule.
  def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
    validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
    setup(new(match), reply_or_type, type, options, block)
  end

  # Converts a class to the correspondent symbol.
  #
  # @param klass [Class] The class to convert.
  # @return [Symbol] The symbol representation of the class.
  def self.resource_class_to_symbol(klass)
    klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
  end

  # Converts a symbol to the correspondent DNS resource class.
  #
  # @param symbol [Symbol] The symbol to convert.
  # @param locale [Symbol] The locale to use for the messages.
  # @return [Symbol] The class associated to the symbol.
  def self.symbol_to_resource_class(symbol, locale = nil)
    symbol = symbol.to_s.upcase

    begin
      "Resolv::DNS::Resource::IN::#{symbol}".constantize
    rescue ::NameError
      raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
    end
  end

  private
    # Setups a new rule.
    #
    # @param match [String|Regexp] The pattern to match.
    # @param reply [String] The IP or hostname to reply back to the client.
    # @param type [Symbol] The type of request to match.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
    def setup(match, reply, type, options, block)
      @match = match
      @type = type || :A
      @reply = block.blank? ? (reply || "127.0.0.1") : nil
      @options = options
      @block = block
    end

    # Validates a newly created rule.
    def validate_rule
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_call)) if @reply.blank? && @block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_options)) if !@options.is_a?(::Hash)
    end

    # Setups a new rule.
    #
    # @param rv [Rule] The rule that is been created.
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @return [Rule] The new rule.
    def self.setup(rv, reply_or_type, type, options = {}, block)
      rv.options = options
      rv.block = block

      if block.present? then # reply_or_type acts like a type, type is ignored
        rv.type = reply_or_type || :A
        rv.reply = nil
      else # reply_or_type acts like a reply
        rv.reply = reply_or_type || "127.0.0.1"
        rv.type = type || :A
      end

      rv
    end

    # Validate options for a new rule creation.
    #
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @param localizer [Localizer] A localizer object.
    def self.validate_options(reply_or_type, options, block, localizer)
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_call)) if reply_or_type.blank? && block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_options)) if !options.is_a?(::Hash)
    end
end

#typeSymbol

Returns The type of request to match. Default: :A. @see .create.

Returns:

  • (Symbol)

    The type of request to match. Default: :A. @see .create



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/devdnsd/rule.rb', line 20

class Rule
  attr_accessor :match
  attr_accessor :type
  attr_accessor :reply
  attr_accessor :options
  attr_accessor :block

  include Lazier::I18n

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply [String] The IP or hostname to reply back to the client.
  # @param type [Symbol] The type of request to match.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
  # @see .create
  def initialize(match = /.+/, reply = "127.0.0.1", type = :A, options = {}, &block)
    i18n_setup(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
    self.i18n = options[:locale]
    setup(match, reply, type, options, block)
    validate_rule
  end

  # Returns the resource class(es) for the current rule.
  #
  # @return [Array|Class] The class(es) for the current rule.
  def resource_class
    classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
    classes.length == 1 ? classes.first : classes
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule is a Regexp, `false` otherwise.
  def is_regexp?
    @match.is_a?(::Regexp)
  end

  # Checks if the rule is a regexp.
  #
  # @return [Boolean] `true` if the rule has a block, `false` otherwise.
  def has_block?
    @block.present?
  end

  # Matches a hostname to the rule.
  #
  # @param hostname [String] The hostname to match.
  # @return [MatchData|Boolean|Nil] Return `true` or MatchData (if the pattern is a regexp) if the rule matches, `false` or `nil` otherwise.
  def match_host(hostname)
    is_regexp? ? @match.match(hostname) : (@match == hostname)
  end

  # Creates a new rule.
  #
  # @param match [String|Regexp] The pattern to match.
  # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
  # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
  # @param options [Hash] A list of options for the request.
  # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
  # @return [Rule] The new rule.
  def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
    validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
    setup(new(match), reply_or_type, type, options, block)
  end

  # Converts a class to the correspondent symbol.
  #
  # @param klass [Class] The class to convert.
  # @return [Symbol] The symbol representation of the class.
  def self.resource_class_to_symbol(klass)
    klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
  end

  # Converts a symbol to the correspondent DNS resource class.
  #
  # @param symbol [Symbol] The symbol to convert.
  # @param locale [Symbol] The locale to use for the messages.
  # @return [Symbol] The class associated to the symbol.
  def self.symbol_to_resource_class(symbol, locale = nil)
    symbol = symbol.to_s.upcase

    begin
      "Resolv::DNS::Resource::IN::#{symbol}".constantize
    rescue ::NameError
      raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
    end
  end

  private
    # Setups a new rule.
    #
    # @param match [String|Regexp] The pattern to match.
    # @param reply [String] The IP or hostname to reply back to the client.
    # @param type [Symbol] The type of request to match.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply` parameter.
    def setup(match, reply, type, options, block)
      @match = match
      @type = type || :A
      @reply = block.blank? ? (reply || "127.0.0.1") : nil
      @options = options
      @block = block
    end

    # Validates a newly created rule.
    def validate_rule
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_call)) if @reply.blank? && @block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(i18n.rule_invalid_options)) if !@options.is_a?(::Hash)
    end

    # Setups a new rule.
    #
    # @param rv [Rule] The rule that is been created.
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param type [Symbol] The type of request to match. This is ignored if a block is provided.
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @return [Rule] The new rule.
    def self.setup(rv, reply_or_type, type, options = {}, block)
      rv.options = options
      rv.block = block

      if block.present? then # reply_or_type acts like a type, type is ignored
        rv.type = reply_or_type || :A
        rv.reply = nil
      else # reply_or_type acts like a reply
        rv.reply = reply_or_type || "127.0.0.1"
        rv.type = type || :A
      end

      rv
    end

    # Validate options for a new rule creation.
    #
    # @param reply_or_type [String|Symbol] The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).
    # @param options [Hash] A list of options for the request.
    # @param block [Proc] An optional block to compute the reply instead of using the `reply_or_type` parameter. In this case `reply_or_type` is used for the type of the request and `type` is ignored.
    # @param localizer [Localizer] A localizer object.
    def self.validate_options(reply_or_type, options, block, localizer)
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_call)) if reply_or_type.blank? && block.nil?
      raise(DevDNSd::Errors::InvalidRule.new(localizer.i18n.rule_invalid_options)) if !options.is_a?(::Hash)
    end
end

Class Method Details

.create(match, reply_or_type = nil, type = nil, options = {}, &block) ⇒ Rule

Creates a new rule.

Parameters:

  • match (String|Regexp)

    The pattern to match.

  • reply_or_type (String|Symbol) (defaults to: nil)

    The IP or hostname to reply back to the client (or the type of request to match, if a block is provided).

  • type (Symbol) (defaults to: nil)

    The type of request to match. This is ignored if a block is provided.

  • options (Hash) (defaults to: {})

    A list of options for the request.

  • block (Proc)

    An optional block to compute the reply instead of using the reply_or_type parameter. In this case reply_or_type is used for the type of the request and type is ignored.

Returns:

  • (Rule)

    The new rule.



82
83
84
85
# File 'lib/devdnsd/rule.rb', line 82

def self.create(match, reply_or_type = nil, type = nil, options = {}, &block)
  validate_options(reply_or_type, options, block, Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), options.is_a?(Hash) ? options[:locale] : nil))
  setup(new(match), reply_or_type, type, options, block)
end

.resource_class_to_symbol(klass) ⇒ Symbol

Converts a class to the correspondent symbol.

Parameters:

  • klass (Class)

    The class to convert.

Returns:

  • (Symbol)

    The symbol representation of the class.



91
92
93
# File 'lib/devdnsd/rule.rb', line 91

def self.resource_class_to_symbol(klass)
  klass.to_s.gsub(/(.+::)?(.+)/, "\\2").to_sym
end

.symbol_to_resource_class(symbol, locale = nil) ⇒ Symbol

Converts a symbol to the correspondent DNS resource class.

Parameters:

  • symbol (Symbol)

    The symbol to convert.

  • locale (Symbol) (defaults to: nil)

    The locale to use for the messages.

Returns:

  • (Symbol)

    The class associated to the symbol.



100
101
102
103
104
105
106
107
108
# File 'lib/devdnsd/rule.rb', line 100

def self.symbol_to_resource_class(symbol, locale = nil)
  symbol = symbol.to_s.upcase

  begin
    "Resolv::DNS::Resource::IN::#{symbol}".constantize
  rescue ::NameError
    raise(DevDNSd::Errors::InvalidRule.new(Lazier::Localizer.new(:devdnsd, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"), locale).i18n.invalid_class(symbol)))
  end
end

Instance Method Details

#has_block?Boolean

Checks if the rule is a regexp.

Returns:

  • (Boolean)

    true if the rule has a block, false otherwise.



62
63
64
# File 'lib/devdnsd/rule.rb', line 62

def has_block?
  @block.present?
end

#is_regexp?Boolean

Checks if the rule is a regexp.

Returns:

  • (Boolean)

    true if the rule is a Regexp, false otherwise.



55
56
57
# File 'lib/devdnsd/rule.rb', line 55

def is_regexp?
  @match.is_a?(::Regexp)
end

#match_host(hostname) ⇒ MatchData|Boolean|Nil

Matches a hostname to the rule.

Parameters:

  • hostname (String)

    The hostname to match.

Returns:

  • (MatchData|Boolean|Nil)

    Return true or MatchData (if the pattern is a regexp) if the rule matches, false or nil otherwise.



70
71
72
# File 'lib/devdnsd/rule.rb', line 70

def match_host(hostname)
  is_regexp? ? @match.match(hostname) : (@match == hostname)
end

#resource_classArray|Class

Returns the resource class(es) for the current rule.

Returns:

  • (Array|Class)

    The class(es) for the current rule.



47
48
49
50
# File 'lib/devdnsd/rule.rb', line 47

def resource_class
  classes = @type.ensure_array(nil, true, true, true) {|cls| self.class.symbol_to_resource_class(cls, options[:locale]) }
  classes.length == 1 ? classes.first : classes
end