nifty-utils 1.0.5 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19691448dc81e33142b1040ffc060db38e0d88c3
4
- data.tar.gz: e24d62684fc507a06d9f5b23cb993953b115b3d7
3
+ metadata.gz: 0f43ab7bf985adc936f4f3d5af7d9aeed18f5874
4
+ data.tar.gz: 8f219e2ad9b79506674ab44989fd62c281d8b933
5
5
  SHA512:
6
- metadata.gz: 8ee820646005e012ebf402eb2ebbcf5c669005135339c1c83d56066bddb40fdc56cc3e3baf3b4cda943d51a3b03f6cb7eae376565eefe729a54a542a858cd449
7
- data.tar.gz: 44a944e51676bdda63e8bc681eeaab061dee98d41dabe0729988d54a88917646a4be3f0a665f10058db908e83bf623c8cecdfc8a737d4dcf61798536396ca08d
6
+ metadata.gz: 01e12d189131662b24b3b31e0c17eb94d339b68fd419e8eaecb4d6a43551d369297cbf3d7c45cd6d58b65898e15b399d0be54a09c52d87436eab365be939e8bf
7
+ data.tar.gz: fe8b782a9f0538d2764b954b4fdc25ba23b5f2dee681859d801745cbbca1b1b45389ea9dc1c5f11b9c96631d8291fb5de237215f60a35fedeec78306d6c4a9d3
@@ -0,0 +1,56 @@
1
+ module Nifty
2
+ module Utils
3
+ module ActiveRecord
4
+ module DefaultValue
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def has_default_values?
13
+ false
14
+ end
15
+
16
+ def default_value(field, block, options = {})
17
+ self.send :include, ModelExtensions unless self.has_default_values?
18
+ self.default_value_definitions[field] = options.merge(:block => block)
19
+ end
20
+
21
+ end
22
+
23
+ module ModelExtensions
24
+
25
+ def self.included(base)
26
+ base.extend ClassMethods
27
+ base.before_validation :_set_default_values
28
+ end
29
+
30
+ def _set_default_values
31
+ self.class.default_value_definitions.each do |field, opts|
32
+ if self.send(field).blank?
33
+ proposed_value = self.instance_exec(&opts[:block])
34
+ self.send("#{field}=", proposed_value)
35
+ end
36
+ end
37
+ end
38
+
39
+ module ClassMethods
40
+
41
+ def default_value_definitions
42
+ @default_value_definitions ||= {}
43
+ end
44
+
45
+ def has_default_values?
46
+ true
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,40 @@
1
+ module Nifty
2
+ module Utils
3
+ module ActiveRecord
4
+ module Inquirer
5
+
6
+ #:nodoc:
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ # Allows you to automatically create inquiry methods for string field. For example, if you have
14
+ # an Order model which has a status field containing 'approved' or 'delivered' you may wish to
15
+ # have a #approved? or #delivered? method on the model.
16
+ #
17
+ # class Order < ActiveRecord::Baser
18
+ # STATUSES = ['approved', 'delivered']
19
+ # inquirer :status, *STATUSES
20
+ # end
21
+ #
22
+ # order = Order.new(:status => 'approved')
23
+ # order.approved? #=> true
24
+ # order.delivered? #=> false
25
+ #
26
+ #
27
+ def inquirer(field, *options)
28
+ options.each do |option|
29
+ define_method "#{option}?" do
30
+ self.read_attribute(field).to_s == option.to_s
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,77 @@
1
+ require 'securerandom'
2
+ require 'nifty/utils/random_string'
3
+
4
+ module Nifty
5
+ module Utils
6
+ module ActiveRecord
7
+ module RandomString
8
+
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ def self.random_string(type, opts = {})
14
+ case type.to_sym
15
+ when :uuid
16
+ SecureRandom.uuid
17
+ when :chars
18
+ Nifty::Utils::RandomString.generate(opts)
19
+ else
20
+ SecureRandom.hex(opts[:length] || 24)
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+
26
+ def has_random_strings?
27
+ false
28
+ end
29
+
30
+ def random_string(field, options = {})
31
+ self.send :include, ModelExtensions unless self.has_random_strings?
32
+ self.random_string_fields[field] = options
33
+ end
34
+
35
+ end
36
+
37
+ module ModelExtensions
38
+
39
+ def self.included(base)
40
+ base.extend ClassMethods
41
+ base.before_validation :generate_random_strings
42
+ end
43
+
44
+ def generate_random_strings
45
+ self.class.random_string_fields.each do |field, opts|
46
+ if self.send(field).blank?
47
+ if opts[:unique]
48
+ until self.send(field)
49
+ proposed_string = RandomString.random_string(opts[:type], opts)
50
+ unless self.class.where(field => proposed_string).exists?
51
+ self.send("#{field}=", proposed_string)
52
+ end
53
+ end
54
+ else
55
+ self.send("#{field}=", RandomString.random_string(opts[:type], opts))
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ module ClassMethods
62
+
63
+ def random_string_fields
64
+ @random_string_fields ||= {}
65
+ end
66
+
67
+ def has_random_strings?
68
+ true
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,70 @@
1
+ module Nifty
2
+ module Utils
3
+ module AutoAttributePermit
4
+
5
+ def self.setup
6
+ ActionView::Helpers::FormBuilder.send :include, FormBuilderExtensions
7
+ ActionController::Parameters.send :include, StrongParameterExtensions
8
+ end
9
+
10
+ def self.verifier
11
+ @verifier ||= ActiveSupport::MessageVerifier.new(Rails.application.secrets.secret_key_base)
12
+ end
13
+
14
+ module StrongParameterExtensions
15
+ def self.included(base)
16
+ base.class_eval do
17
+ alias_method_chain :permit, :auto_attribute_permit
18
+ end
19
+ end
20
+
21
+ def permit_with_auto_attribute_permit(*filters)
22
+ if filters.delete(:auto)
23
+ fields = AutoAttributePermit.verifier.verify(self['permitted_fields'])
24
+ permit_without_auto_attribute_permit(*(fields | filters))
25
+ else
26
+ permit_without_auto_attribute_permit(*filters)
27
+ end
28
+ end
29
+ end
30
+
31
+ module FormBuilderExtensions
32
+ def self.included(base)
33
+ base.class_eval do
34
+ alias_method_chain :label, :auto_attribute_permit
35
+ alias_method_chain :submit, :auto_attribute_permit
36
+ end
37
+ end
38
+
39
+ def auto_permitted_attributes
40
+ @auto_permitted_attributes ||= []
41
+ end
42
+
43
+ def label_with_auto_attribute_permit(method, text = nil, options = {}, &block)
44
+ auto_permitted_attributes << method unless (text.is_a?(Hash) ? text : options)[:auto_permit] == false
45
+ label_without_auto_attribute_permit(method, text, options, &block)
46
+ end
47
+
48
+ def submit_with_auto_attribute_permit(value = nil, options = {})
49
+ value, options = nil, value if value.is_a?(Hash)
50
+ include_permit_field = options.delete(:include_auto_permit_field)
51
+ submit_button = submit_without_auto_attribute_permit(value, options)
52
+ unless include_permit_field == false
53
+ submit_button.safe_concat(self.auto_permitted_attributes_field)
54
+ else
55
+ submit_button
56
+ end
57
+ end
58
+
59
+ def encoded_auto_permitted_attributes
60
+ AutoAttributePermit.verifier.generate(auto_permitted_attributes)
61
+ end
62
+
63
+ def auto_permitted_attributes_field
64
+ @template.hidden_field_tag("#{@object_name}[permitted_fields]", encoded_auto_permitted_attributes)
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -1 +1,2 @@
1
- require 'nifty/utils/extensions/string'
1
+ require 'nifty/utils/extensions/object'
2
+ require 'nifty/utils/extensions/string'
@@ -0,0 +1,9 @@
1
+ require 'nifty/utils/until_with_max_attempts'
2
+
3
+ class Object
4
+
5
+ def until_with_max_attempts(*args, &block)
6
+ Nifty::Utils::UntilWithMaxAttempts.until(*args, &block)
7
+ end
8
+
9
+ end
@@ -1,7 +1,7 @@
1
1
  require 'nifty/utils/random_string'
2
2
 
3
3
  class String
4
-
4
+
5
5
  def self.random(options = {})
6
6
  Nifty::Utils::RandomString.generate(options)
7
7
  end
@@ -9,17 +9,21 @@ class String
9
9
  def ansi(code)
10
10
  "\e[#{code.to_s}m#{self}\e[0m"
11
11
  end
12
-
12
+
13
13
  def red
14
14
  self.ansi(31)
15
15
  end
16
-
16
+
17
17
  def green
18
18
  self.ansi(32)
19
19
  end
20
-
21
- def yello
20
+
21
+ def yellow
22
22
  self.ansi(33)
23
23
  end
24
-
24
+
25
+ def blue
26
+ self.ansi(34)
27
+ end
28
+
25
29
  end
@@ -0,0 +1,78 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+
4
+ module Nifty
5
+ module Utils
6
+ module HTTP
7
+
8
+ def self.get(url, options = {})
9
+ request(Net::HTTP::Get, url, options)
10
+ end
11
+
12
+ def self.post(url, options = {})
13
+ request(Net::HTTP::Post, url, options)
14
+ end
15
+
16
+ def self.request(method, url, options = {})
17
+ options[:headers] ||= {}
18
+ uri = URI.parse(url)
19
+ request = method.new(uri.path.length == 0 ? "/" : uri.path)
20
+ options[:headers].each { |k,v| request.add_field k, v }
21
+
22
+ if options[:username]
23
+ request.basic_auth(options[:username], options[:password])
24
+ end
25
+
26
+ if options[:params].is_a?(Hash)
27
+ # If params has been provided, sent it them as form encoded values
28
+ request.set_form_data(options[:params])
29
+
30
+ elsif options[:json].is_a?(String)
31
+ # If we have a JSON string, set the content type and body to be the JSON
32
+ # data
33
+ request.add_field 'Content-Type', 'application/json'
34
+ request.body = options[:json]
35
+ end
36
+
37
+ if options[:user_agent]
38
+ request['User-Agent'] = options[:user_agent]
39
+ end
40
+
41
+ connection = Net::HTTP.new(uri.host, uri.port)
42
+
43
+ if uri.scheme == 'https'
44
+ connection.use_ssl = true
45
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
46
+ end
47
+
48
+ begin
49
+ timeout = options[:timeout] || 60
50
+ Timeout.timeout(timeout) do
51
+ result = connection.request(request)
52
+ if result.content_type == 'application/json'
53
+ body = JSON.parse(result.body)
54
+ else
55
+ body = result.body
56
+ end
57
+ {
58
+ :code => result.code.to_i,
59
+ :type => result.content_type,
60
+ :body => body
61
+ }
62
+ end
63
+ rescue SocketError, Errno::ECONNRESET, EOFError, Errno::EINVAL => e
64
+ {
65
+ :code => -2,
66
+ :body => e.message
67
+ }
68
+ rescue Timeout::Error => e
69
+ {
70
+ :code => -1,
71
+ :body => "Timed out after #{timeout}s"
72
+ }
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ require 'ipaddr'
2
+
3
+ module Nifty
4
+ module Utils
5
+ module Networks
6
+
7
+ def self.ip_in_networks?(ip, networks = [])
8
+ !!network_for_ip(networks, ip)
9
+ end
10
+
11
+ def self.network_for_ip(networks, ip)
12
+ networks.each do |i|
13
+ if IPAddr.new(i).include?(ip)
14
+ return i
15
+ end
16
+ end
17
+ return nil
18
+ rescue ArgumentError => e
19
+ if e.message == 'invalid address'
20
+ return nil
21
+ else
22
+ raise
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -1,23 +1,28 @@
1
1
  module Nifty
2
2
  module Utils
3
3
  class Railtie < Rails::Railtie #:nodoc:
4
-
5
- initializer 'nifty.utils.initialize' do
4
+
5
+ initializer 'nifty.utils.initialize' do |app|
6
+ Rails.application.config.i18n.load_path << File.expand_path(File.join('..', '..', '..', '..', 'locales', 'en.yml'), __FILE__)
6
7
 
7
8
  # Load the Active Record extensions
8
9
  ActiveSupport.on_load(:active_record) do
9
- require 'nifty/utils/active_record'
10
- ::ActiveRecord::Base.send :include, Nifty::Utils::ActiveRecord
10
+ require 'nifty/utils/active_record/inquirer'
11
+ ::ActiveRecord::Base.send :include, Nifty::Utils::ActiveRecord::Inquirer
12
+ require 'nifty/utils/active_record/random_string'
13
+ ::ActiveRecord::Base.send :include, Nifty::Utils::ActiveRecord::RandomString
14
+ require 'nifty/utils/active_record/default_value'
15
+ ::ActiveRecord::Base.send :include, Nifty::Utils::ActiveRecord::DefaultValue
11
16
  end
12
-
17
+
13
18
  # load the Action View helpers
14
19
  ActiveSupport.on_load(:action_view) do
15
20
  require 'nifty/utils/view_helpers'
16
21
  ActionView::Base.send :include, Nifty::Utils::ViewHelpers
17
22
  end
18
-
23
+
19
24
  end
20
-
25
+
21
26
  end
22
27
  end
23
28
  end
@@ -0,0 +1,45 @@
1
+ module Nifty
2
+ module Utils
3
+ module UntilWithMaxAttempts
4
+
5
+ #
6
+ # The exception which will be raised if the maximum number of attempts
7
+ # is reached.
8
+ #
9
+ class MaxAttemptsReached < StandardError; end
10
+
11
+ #
12
+ # Like a usual while block but with a maximum attempt counter. Can be used
13
+ # like this
14
+ #
15
+ # Attempts.until proc { job.completed? }, :attempts => 10, :gap => 5 do
16
+ # puts "Waiting for job to complete..."
17
+ # end
18
+ #
19
+ # The proc is the condition which will be evaluated, :attempts sets the
20
+ # maximum number of times it will wait before raising an exception and :gap
21
+ # is the length of time in seconds to wait between each check.
22
+ #
23
+ def self.until(condition, options = {}, &block)
24
+ options[:attempts] ||= 10
25
+ count = 0
26
+ until condition.call
27
+
28
+ if count == options[:attempts]
29
+ raise MaxAttemptsReached, "Maximum attempts reached (#{options[:attempts]}) without success"
30
+ end
31
+
32
+ yield
33
+
34
+ count += 1
35
+
36
+ if options[:gap] && count < options[:attempts]
37
+ sleep options[:gap]
38
+ end
39
+
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -1,5 +1,5 @@
1
1
  module Nifty
2
2
  module Utils
3
- VERSION = '1.0.5'
3
+ VERSION = '1.1.7'
4
4
  end
5
5
  end
@@ -1,21 +1,24 @@
1
1
  module Nifty
2
2
  module Utils
3
3
  module ViewHelpers
4
-
4
+
5
5
  # Displays the full contents of the `flash` hash within an appropriate <div>
6
6
  # element. The ID of the outputted div will be `flash-alert` where alert is the
7
- # type of flash.
7
+ # type of flash.
8
8
  #
9
- # If there are multiple flashes set, they will all be displayed.
10
- def display_flash
11
- flashes = flash.collect do |key,msg|
12
- content_tag :div, content_tag(:p, h(msg)), :id => "flash-#{key}"
9
+ # * <tt>:types</tt>: the names of flash messages to display with this helper
10
+ def display_flash(options = {})
11
+ options[:types] ||= [:alert, :warning, :notice]
12
+ options[:types].map do |key|
13
+ if flash[key]
14
+ content_tag :div, content_tag(:p, h(flash[key])), :id => "flash-#{key}", :class => "flashMessage flashMessage--#{key}"
15
+ end
13
16
  end.join.html_safe
14
17
  end
15
-
18
+
16
19
  # Renders an `<img>` containing a link to the gravatar for the given e-mail address.
17
20
  # Available options as follows:
18
- #
21
+ #
19
22
  # * <tt>:size</tt>: the size in pixels of the outputted gravatar. Defaults to 35.
20
23
  # * <tt>:default</tt>: the gravatar to fallback to if the user has no gravatar
21
24
  # (see gravatar for available options or pass a URL). Defaults to 'identicon'.
@@ -34,10 +37,10 @@ module Nifty
34
37
  path = "/avatar.php?gravatar_id=#{Digest::MD5.hexdigest(email.to_s.downcase)}&rating=#{options[:rating]}&size=#{options[:size] * 2}&d=#{options[:default]}"
35
38
  image_tag([host,path].join, :class => options[:class], :width => options[:size], :height => options[:size])
36
39
  end
37
-
40
+
38
41
  # Renders a tick or cross character based on the provided boolean. Additional options
39
42
  # can be passed if needed.
40
- #
43
+ #
41
44
  # * <tt>:true_text</tt> - text to display next to a tick
42
45
  # * <tt>:false_text</tt> - text to display next to a cross
43
46
  def boolean_tag(bool, tip = nil, options = {})
@@ -46,7 +49,53 @@ module Nifty
46
49
  false_text = " <b>#{options[:false_text]}</b>" if options[:false_text]
47
50
  content_tag :span, (bool ? "<span class='true'>&#x2714;#{true_text}</span>" : "<span class='false'>&#x2718;#{false_text}</span>").html_safe, :class => "boolean", :title => tip
48
51
  end
49
-
52
+
53
+ # Returns a URL to share some content on Twitter
54
+ #
55
+ # * <tt>:text</tt> - the text you wish to tweet
56
+ # * <tt>:url</tt> - the URL you want to tweet
57
+ def twitter_share_url(options = {})
58
+ "https://twitter.com/share?text=#{CGI.escape(options[:text])}&url=#{CGI.escape(options[:url])}"
59
+ end
60
+
61
+ # Returns a length of time in works (no I18N)
62
+ #
63
+ def length_of_time_in_words(seconds, options = {})
64
+ days = (seconds / 60 / 60 / 24).floor
65
+ hours = ((seconds / 60 / 60) - (days * 24)).floor
66
+ minutes = ((seconds / 60) - (days * 24 * 60) - (hours * 60)).floor
67
+ seconds = (seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60)).floor
68
+ Array.new.tap do |s|
69
+ if options[:short]
70
+ s << "#{days}d" if days > 0
71
+ s << "#{hours}h" if hours > 0
72
+ s << "#{minutes}m" if minutes > 0
73
+ s << "#{seconds}s" if seconds > 0
74
+ else
75
+ s << pluralize(days, 'day') if days > 0
76
+ s << pluralize(hours, 'hour') if hours > 0
77
+ s << pluralize(minutes, 'minute') if minutes > 0
78
+ s << pluralize(seconds, 'second') if seconds > 0
79
+ end
80
+ end.join(options[:short] ? ' ' : ', ')
81
+ end
82
+
83
+ # Return an image path for an RFC4226 QR code for a tiven RTP token
84
+ def rfc4226_qrcode(token)
85
+ data = "otpauth://totp/#{request.host}?secret=#{token}"
86
+ data = Rack::Utils.escape(data)
87
+ url = "https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=#{data}"
88
+ image_tag(url, :alt => 'Google Authenticator QRCode', :width => 200, :height => 200)
89
+ end
90
+
91
+ # Return a Google Fonts tag
92
+ def google_fonts(sets = {})
93
+ sets = sets.each_with_object([]) do |(name, weights), array|
94
+ array << "#{name}:#{weights.join(',')}"
95
+ end.join('|')
96
+ "<link href='https://fonts.googleapis.com/css?family=#{sets}' rel='stylesheet' type='text/css'>".html_safe
97
+ end
98
+
50
99
  end
51
100
  end
52
101
  end
data/locales/en.yml ADDED
@@ -0,0 +1,4 @@
1
+ en:
2
+ nifty-utils:
3
+ hello: Hello world!
4
+
metadata CHANGED
@@ -1,32 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nifty-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Cooke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-24 00:00:00.000000000 Z
11
+ date: 2015-06-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A set of useful utilties for Rails applications
13
+ description: A set of useful utilties for Rails applications.
14
14
  email:
15
- - adam@niftyware.io
15
+ - adam@atechmedia.com
16
16
  executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - lib/nifty/utils.rb
21
- - lib/nifty/utils/active_record.rb
21
+ - lib/nifty/utils/active_record/default_value.rb
22
+ - lib/nifty/utils/active_record/inquirer.rb
23
+ - lib/nifty/utils/active_record/random_string.rb
24
+ - lib/nifty/utils/auto_attribute_permit.rb
22
25
  - lib/nifty/utils/extensions/core.rb
26
+ - lib/nifty/utils/extensions/object.rb
23
27
  - lib/nifty/utils/extensions/string.rb
28
+ - lib/nifty/utils/http.rb
29
+ - lib/nifty/utils/networks.rb
24
30
  - lib/nifty/utils/railtie.rb
25
31
  - lib/nifty/utils/random_string.rb
32
+ - lib/nifty/utils/until_with_max_attempts.rb
26
33
  - lib/nifty/utils/version.rb
27
34
  - lib/nifty/utils/view_helpers.rb
28
- homepage: https://github.com/niftyware/utils
29
- licenses: []
35
+ - locales/en.yml
36
+ homepage: https://github.com/atech/nifty-utils
37
+ licenses:
38
+ - MIT
30
39
  metadata: {}
31
40
  post_install_message:
32
41
  rdoc_options: []
@@ -44,9 +53,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
44
53
  version: '0'
45
54
  requirements: []
46
55
  rubyforge_project:
47
- rubygems_version: 2.2.2
56
+ rubygems_version: 2.4.5
48
57
  signing_key:
49
58
  specification_version: 4
50
- summary: A set of useful utilties for Rails applications
59
+ summary: A collection of functions which expand upon ActiveRecord and ActionView.
51
60
  test_files: []
52
- has_rdoc:
@@ -1,38 +0,0 @@
1
- module Nifty
2
- module Utils
3
- module ActiveRecord
4
-
5
- #:nodoc:
6
- def self.included(base)
7
- base.extend ClassMethods
8
- end
9
-
10
- module ClassMethods
11
-
12
- # Allows you to automatically create inquiry methods for string field. For example, if you have
13
- # an Order model which has a status field containing 'approved' or 'delivered' you may wish to
14
- # have a #approved? or #delivered? method on the model.
15
- #
16
- # class Order < ActiveRecord::Baser
17
- # STATUSES = ['approved', 'delivered']
18
- # inquirer :status, *STATUSES
19
- # end
20
- #
21
- # order = Order.new(:status => 'approved')
22
- # order.approved? #=> true
23
- # order.delivered? #=> false
24
- #
25
- #
26
- def inquirer(field, *options)
27
- options.each do |option|
28
- define_method "#{option}?" do
29
- self.read_attribute(field).to_s == option.to_s
30
- end
31
- end
32
- end
33
-
34
- end
35
-
36
- end
37
- end
38
- end