Module: PropertySets::ActiveRecordExtension::ClassMethods

Defined in:
lib/property_sets/active_record_extension.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#property_sets_connection_classObject

Returns the value of attribute property_sets_connection_class.



7
8
9
# File 'lib/property_sets/active_record_extension.rb', line 7

def property_sets_connection_class
  @property_sets_connection_class
end

Instance Method Details

#property_set(association, options = {}, &block) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
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
# File 'lib/property_sets/active_record_extension.rb', line 9

def property_set(association, options = {}, &block)
  unless include?(PropertySets::ActiveRecordExtension::InstanceMethods)
    send(:prepend, PropertySets::ActiveRecordExtension::InstanceMethods)
    cattr_accessor :property_set_index
    self.property_set_index = Set.new
  end

  raise "Invalid association name, letters only" unless /[a-z]+/.match?(association.to_s)
  exists = property_set_index.include?(association)

  property_set_index << association

  # eg AccountSetting - this IS idempotent
  property_class = PropertySets.ensure_property_set_class(
    association,
    options.delete(:owner_class_name) || name
  )

  # eg property :is_awesome
  property_class.instance_eval(&block) if block

  tb_name = options.delete :table_name
  property_class.table_name = tb_name if tb_name

  hash_opts = {
    class_name: property_class.name,
    autosave: true,
    dependent: :destroy,
    inverse_of: name.demodulize.underscore.to_sym
  }.merge(options)

  # TODO: should check options are compatible? warn? raise?
  reflection = reflections[association.to_s] # => ActiveRecord::Reflection::HasManyReflection
  reflection.options.merge! options if reflection && !options.empty?

  unless exists # makes has_many idempotent...
    has_many association, **hash_opts do
      # keep this damn block! -- creates association_module below
    end
  end

  # stolen/adapted from AR's collection_association.rb #define_extensions

  module_name = "#{association.to_s.camelize}AssociationExtension"
  association_module = const_get module_name

  association_module.module_eval do
    include PropertySets::ActiveRecordExtension::AssociationExtensions

    property_class.keys.each do |key|
      raise "Invalid property key #{key}" if respond_to?(key)

      # Reports the coerced truth value of the property
      define_method :"#{key}?" do
        type = property_class.type(key)
        value = lookup_value(type, key)
        !["false", "0", "", "off", "n"].member?(value.to_s.downcase)
      end

      # Returns the value of the property
      define_method key.to_s do
        type = property_class.type(key)
        lookup_value(type, key)
      end

      # Assigns a new value to the property
      define_method :"#{key}=" do |value|
        instance = lookup(key)
        instance.value = PropertySets::Casting.write(property_class.type(key), value)
        instance.value
      end

      define_method :"#{key}_record" do
        lookup(key)
      end
    end

    define_method :property_serialized? do |key|
      property_class.type(key) == :serialized
    end
  end
end