Module: PropertySets::ActiveRecordExtension::ClassMethods

Defined in:
lib/property_sets/active_record_extension.rb

Instance Method Summary collapse

Instance Method Details

#property_set(association, &block) ⇒ Object



4
5
6
7
8
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
# File 'lib/property_sets/active_record_extension.rb', line 4

def property_set(association, &block)
  unless include?(PropertySets::ActiveRecordExtension::InstanceMethods)
    self.send(:include, PropertySets::ActiveRecordExtension::InstanceMethods)
    cattr_accessor :property_set_index
    self.property_set_index = []
  end

  raise "Invalid association name, letters only" unless association.to_s =~ /[a-z]+/
  self.property_set_index << association

  property_class = PropertySets.ensure_property_set_class(association, self)
  property_class.instance_eval(&block)

  has_many association, :class_name => property_class.name, :dependent => :destroy do

    # Accepts a name value pair hash { :name => 'value', :pairs => true } and builds a property for each key
    def set(property_pairs, with_protection = false)
      property_pairs.keys.each do |name|
        record = lookup(name)
        if with_protection && record.protected?
          logger.warn("Someone tried to update the protected #{name} property to #{property_pairs[name]}")
        else
          send("#{name}=", property_pairs[name])
        end
      end
    end

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

      # Reports the coerced truth value of the property
      define_method "#{key}?" do
        lookup_or_default(key).true?
      end

      # Returns the value of the property
      define_method "#{key}" do
        lookup(key).value
      end

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

      define_method "protected?" do |arg|
        lookup(arg).protected?
      end

      define_method "enable" do |arg|
        send("#{arg}=", "1")
      end

      define_method "disable" do |arg|
        send("#{arg}=", "0")
      end

      # Assigns a new value to the property
      define_method "#{key}=" do |value|
        instance = lookup(key)
        instance.value = value
        @owner.send(association) << instance
        value
      end

      # The finder method which returns the property if present, otherwise a new instance with defaults
      define_method "lookup" do |arg|
        instance   = detect { |property| property.name.to_sym == arg.to_sym }
        instance ||= build(:name => arg.to_s, :value => property_class.default(arg))

        instance.send("#{owner_class_sym}=", @owner) if @owner.new_record?

        instance
      end

      # This finder method returns the property if present,
      #   otherwise a new instance with the default value.
      # It does not have the side effect of adding a new setting object.
      define_method 'lookup_or_default' do |arg|
        instance = detect { |property| property.name.to_sym == arg.to_sym }
        instance ||= property_class.new(:value => property_class.default(arg))
      end

    end
  end
end