Class: RailsStuff::Statusable::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_stuff/statusable.rb

Overview

Generates methods and scopes.

Direct Known Subclasses

MappedBuilder

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, field, statuses, **options) ⇒ Builder

Returns a new instance of Builder.



64
65
66
67
68
69
70
71
# File 'lib/rails_stuff/statusable.rb', line 64

def initialize(model, field, statuses, **options)
  @model = model
  @field = field
  @statuses = statuses
  @options = options
  @prefix = options[:prefix]
  @suffix = options[:suffix]
end

Instance Attribute Details

#fieldObject (readonly)

Returns the value of attribute field.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def field
  @field
end

#modelObject (readonly)

Returns the value of attribute model.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def model
  @model
end

#optionsObject (readonly)

Returns the value of attribute options.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def options
  @options
end

#prefixObject (readonly)

Returns the value of attribute prefix.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def prefix
  @prefix
end

#statusesObject (readonly) Also known as: statuses_list

Returns the value of attribute statuses.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def statuses
  @statuses
end

#suffixObject (readonly)

Returns the value of attribute suffix.



61
62
63
# File 'lib/rails_stuff/statusable.rb', line 61

def suffix
  @suffix
end

Instance Method Details

#define_method(method, &block) ⇒ Object



171
172
173
# File 'lib/rails_stuff/statusable.rb', line 171

def define_method(method, &block)
  model.statusable_methods.send(:define_method, method, &block)
end

#define_scope(name, body) ⇒ Object

Rails 4 doesn’t use ‘instance_exec` for scopes, so we do it manually.



165
166
167
168
169
# File 'lib/rails_stuff/statusable.rb', line 165

def define_scope(name, body)
  model.singleton_class.send(:define_method, name) do |*args|
    all.scoping { instance_exec(*args, &body) } || all
  end
end

#field_readerObject

Status as symbol.



130
131
132
133
134
135
136
# File 'lib/rails_stuff/statusable.rb', line 130

def field_reader
  field = self.field
  define_method "#{field}_sym" do
    val = send(field)
    val && val.to_sym
  end
end

#field_scopeObject

Scope with given status. Useful for has_scope.



89
90
91
92
# File 'lib/rails_stuff/statusable.rb', line 89

def field_scope
  field = self.field
  define_scope "with_#{field}", ->(status) { where(field => status) }
end

#field_writerObject

Make field accept sympbols.



122
123
124
125
126
127
# File 'lib/rails_stuff/statusable.rb', line 122

def field_writer
  define_method "#{field}=" do |val|
    val = val.to_s if val.is_a?(Symbol)
    super(val)
  end
end

#generateObject



73
74
75
76
77
78
79
80
81
# File 'lib/rails_stuff/statusable.rb', line 73

def generate
  validations unless options[:validate] == false
  field_reader
  field_writer
  select_options_helper
  translation_helpers
  field_scope
  value_methods
end

#generate_class_method(method, &block) ⇒ Object



175
176
177
# File 'lib/rails_stuff/statusable.rb', line 175

def generate_class_method(method, &block)
  model.statusable_methods::ClassMethods.send(:define_method, method, &block)
end

#select_options_helperObject



154
155
156
157
158
159
160
161
162
# File 'lib/rails_stuff/statusable.rb', line 154

def select_options_helper
  statuses_list = self.statuses_list
  translation_method = :"#{field}_name"
  # Returns array compatible with select_options helper.
  generate_class_method "#{field}_select_options" do |args = {}|
    filtered_statuses = statuses_list - Array.wrap(args[:except])
    filtered_statuses.map { |x| [send(translation_method, x), x] }
  end
end

#status_accessor(status_name, value) ⇒ Object

Generates methods for specific value.



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rails_stuff/statusable.rb', line 107

def status_accessor(status_name, value)
  field = self.field

  # Shortcut to check status.
  define_method "#{prefix}#{status_name}#{suffix}?" do
    self[field] == value
  end

  # Shortcut to update status.
  define_method "#{prefix}#{status_name}#{suffix}!" do
    update_attributes!(field => value)
  end
end

#translation_helpersObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rails_stuff/statusable.rb', line 138

def translation_helpers
  field = self.field
  sym_method = "#{field}_sym"

  # Class-level translation helper.
  generate_class_method "#{field}_name" do |status|
    t(".#{field}_name.#{status}") if status
  end

  # Translation helper.
  define_method "#{field}_name" do
    val = send(sym_method)
    self.class.t(".#{field}_name.#{val}") if val
  end
end

#validationsObject



83
84
85
86
# File 'lib/rails_stuff/statusable.rb', line 83

def validations
  model.validates_inclusion_of field,
    {in: statuses.map(&:to_s)}.merge!(options.fetch(:validate, {}))
end

#value_methodsObject



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rails_stuff/statusable.rb', line 94

def value_methods
  field = self.field
  statuses.map(&:to_s).each do |status_name|
    # Scopes for every status.
    define_scope "#{prefix}#{status_name}#{suffix}",
      -> { where(field => status_name) }
    define_scope "not_#{prefix}#{status_name}#{suffix}",
      -> { where.not(field => status_name) }
    status_accessor status_name, status_name
  end
end