Module: Trax::Model::ExtensionsFor::Struct::ClassMethods

Defined in:
lib/trax/model/extensions_for/struct.rb

Instance Method Summary collapse

Instance Method Details

#[](val) ⇒ Object



26
27
28
# File 'lib/trax/model/extensions_for/struct.rb', line 26

def [](val)
  fields[val]
end

#define_model_scope_for(attribute_name, **options) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/trax/model/extensions_for/struct.rb', line 50

def define_model_scope_for(attribute_name, **options)
  attribute_klass = fields[attribute_name]

  case fields[attribute_name].type
  when :boolean
    define_where_scopes_for_boolean_property(attribute_name, attribute_klass, **options)
  when :enum
    define_scopes_for_enum(attribute_name, attribute_klass, **options)
  when :array
    define_scopes_for_array(attribute_name, attribute_klass, **options)
  when :integer
    define_scopes_for_numeric(attribute_name, attribute_klass, **options)
  when :time
    define_scopes_for_time(attribute_name, attribute_klass, **options)
  else
    define_where_scopes_for_property(attribute_name, attribute_klass, **options)
  end
end

#define_model_scopes_for(*attribute_names) ⇒ Object



44
45
46
47
48
# File 'lib/trax/model/extensions_for/struct.rb', line 44

def define_model_scopes_for(*attribute_names)
  attribute_names.each do |attribute_name|
    define_model_scope_for(attribute_name)
  end
end

#define_scopes_for_array(attribute_name, property_klass, as: nil) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/trax/model/extensions_for/struct.rb', line 69

def define_scopes_for_array(attribute_name, property_klass, as:nil)
  return unless has_active_record_ancestry?(property_klass)

  model_class = model_class_for_property(property_klass)
  field_name = property_klass.parent_definition.name.demodulize.underscore
  attribute_name = property_klass.name.demodulize.underscore
  scope_name = as || :"by_#{field_name}_#{attribute_name}"

  model_class.scope(scope_name, lambda{ |*_scope_values|
    _scope_values.flat_compact_uniq!
    model_class.where("#{field_name} -> '#{attribute_name}' ?| array[:values]", :values => _scope_values)
  })
end

#define_scopes_for_enum(attribute_name, enum_klass, as: nil) ⇒ Object

this only supports properties 1 level deep, but works beautifully I.E. for this structure define_attributes do

struct :custom_fields do
  enum :color, :default => :blue do
    define :blue,     1
    define :red,      2
    define :green,    3
  end
end

end ::Product.by_custom_fields_color(:blue, :red) will return #color=blue, #color=red



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/trax/model/extensions_for/struct.rb', line 135

def define_scopes_for_enum(attribute_name, enum_klass, as:nil)
  return unless has_active_record_ancestry?(enum_klass)

  model_class = model_class_for_property(enum_klass)
  field_name = enum_klass.parent_definition.name.demodulize.underscore
  attribute_name = enum_klass.name.demodulize.underscore
  scope_name = as || :"by_#{field_name}_#{attribute_name}"
  model_class.scope(scope_name, lambda{ |*_scope_values|
    _integer_values = enum_klass.select_values(*_scope_values.flat_compact_uniq!)
    _integer_values.map!(&:to_s)
    model_class.where("#{field_name} -> '#{attribute_name}' IN(?)", _integer_values)
  })
end

#define_scopes_for_numeric(attribute_name, property_klass, as: nil) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/trax/model/extensions_for/struct.rb', line 83

def define_scopes_for_numeric(attribute_name, property_klass, as:nil)
  return unless has_active_record_ancestry?(property_klass)

  model_class = model_class_for_property(property_klass)
  field_name = property_klass.parent_definition.name.demodulize.underscore
  attribute_name = property_klass.name.demodulize.underscore
  cast_type = property_klass.type

  { :gt => '>', :gte => '>=', :lt => '<', :lte => '<=', :eq => '='}.each_pair do |k, operator|
    scope_name = as ? :"#{as}_#{k}" : :"by_#{field_name}_#{attribute_name}_#{k}"

    model_class.scope(scope_name, lambda{ |*_scope_values|
      _scope_values.flat_compact_uniq!
      model_class.where("(#{field_name} ->> '#{attribute_name}')::#{cast_type} #{operator} ?", _scope_values)
    })
  end
end

#define_scopes_for_time(attribute_name, property_klass, as: nil) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/trax/model/extensions_for/struct.rb', line 101

def define_scopes_for_time(attribute_name, property_klass, as:nil)
  return unless has_active_record_ancestry?(property_klass)

  model_class = model_class_for_property(property_klass)
  field_name = property_klass.parent_definition.name.demodulize.underscore
  attribute_name = property_klass.name.demodulize.underscore
  cast_type = 'timestamp'

  { :gt => '>', :lt => '<'}.each_pair do |k, operator|
    scope_prefix = as ? as : :"by_#{field_name}_#{attribute_name}"
    scope_name = "#{scope_prefix}_#{k}"
    scope_alias = "#{scope_prefix}_#{{:gt => 'after', :lt => 'before' }[k]}"

    model_class.scope(scope_name, lambda{ |*_scope_values|
      _scope_values.flat_compact_uniq!
      model_class.where("(#{field_name} ->> '#{attribute_name}')::#{cast_type} #{operator} ?", _scope_values)
    })
    model_class.singleton_class.__send__("alias_method", scope_alias.to_sym, scope_name)
  end
end

#define_where_scopes_for_boolean_property(attribute_name, property_klass, as: nil) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/trax/model/extensions_for/struct.rb', line 149

def define_where_scopes_for_boolean_property(attribute_name, property_klass, as:nil)
  return unless has_active_record_ancestry?(property_klass)

  model_class = model_class_for_property(property_klass)
  field_name = property_klass.parent_definition.name.demodulize.underscore
  attribute_name = property_klass.name.demodulize.underscore
  scope_name = as || :"by_#{field_name}_#{attribute_name}"
  model_class.scope(scope_name, lambda{ |*_scope_values|
    _scope_values.map!(&:to_s).flat_compact_uniq!
    model_class.where("#{field_name} -> '#{attribute_name}' IN(?)", _scope_values)
  })
end

#define_where_scopes_for_property(attribute_name, property_klass, as: nil) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/trax/model/extensions_for/struct.rb', line 162

def define_where_scopes_for_property(attribute_name, property_klass, as:nil)
  return unless has_active_record_ancestry?(property_klass)

  model_class = model_class_for_property(property_klass)
  field_name = property_klass.parent_definition.name.demodulize.underscore
  attribute_name = property_klass.name.demodulize.underscore
  scope_name = as || :"by_#{field_name}_#{attribute_name}"

  model_class.scope(scope_name, lambda{ |*_scope_values|
    _scope_values.map!(&:to_s).flat_compact_uniq!
    model_class.where("#{field_name} ->> '#{attribute_name}' IN(?)", _scope_values)
  })
end

#has_active_record_ancestry?(property_klass) ⇒ Boolean

Returns:



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/trax/model/extensions_for/struct.rb', line 176

def has_active_record_ancestry?(property_klass)
  return false unless property_klass.respond_to?(:parent_definition)

  result = if property_klass.parent_definition.ancestors.include?(::ActiveRecord::Base)
    true
  else
    has_active_record_ancestry?(property_klass.parent_definition)
  end

  result
end

#permitted_keysObject

bit of a hack for the sake of strong params for now



30
31
32
# File 'lib/trax/model/extensions_for/struct.rb', line 30

def permitted_keys
  @permitted_keys ||= properties.map(&:to_sym)
end

#property(property_name, *args, **options) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/trax/model/extensions_for/struct.rb', line 34

def property(property_name, *args, **options)
  super(property_name, *args, **options)

  extensions_for_property_type = ::Trax::Model::ExtensionsFor::StructFields[self.fields[property_name].type]

  if extensions_for_property_type
    self.fields[property_name].include(extensions_for_property_type)
  end
end