Module: Skyline::BelongsToReferable::ClassMethods

Defined in:
lib/skyline/belongs_to_referable.rb

Instance Method Summary collapse

Instance Method Details

#belongs_to_referable(*fields, options = {}) ⇒ void

This method returns an undefined value.

Defines a relationship to a referable.

Parameters:

  • *fields (String, Symbol)

    The referable(s) to create associations to.

Options Hash (options):

  • :allow_nil (true, false) — default: true

    Allow this association to be empty?

See Also:



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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/skyline/belongs_to_referable.rb', line 64

def belongs_to_referable(*fields)
  options = fields.extract_options!.reverse_merge(:allow_nil => true)
  fields.each do |f|
    self.referable_contents << f
            
    belongs_to f, :class_name => "Skyline::ObjectRef", :foreign_key => "#{f}_id", :dependent => :destroy
    accepts_nested_attributes_for f, :reject_if => proc {|attributes| attributes['referable_type'].blank?}, :allow_destroy => true

    unless options[:allow_nil]
      # validating on :linked instead of :linked_id here; see:
      #   http://railsforum.com/viewtopic.php?id=30300
      #   https://rails.lighthouseapp.com/projects/8994/tickets/1943
      #   https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2815-nested-models-build-should-directly-assign-the-parent          
      validates_presence_of f
    end

    self.class_eval(<<-END, __FILE__, __LINE__ + 1)
      def #{f}_with_passthrough=(obj)
        if obj.kind_of?(Skyline::ObjectRef)
          self.#{f}_without_passthrough = obj
        else
          self.attributes = {"#{f}_attributes" => {:referable_type => obj.class.name, :referable_id => obj.id}}
        end
      end
      alias_method_chain :#{f}=, :passthrough
      
      def #{f}_attributes=(attributes)
        referable_params = attributes.delete("referable_attributes")
        self.previous_referables ||= {}
        self.previous_referables[:#{f}] = self.#{f}.referable.dup if self.#{f}.andand.referable
        assign_nested_attributes_for_one_to_one_association(:#{f}, attributes)
  
        # only create and modify referable if it is a Skyline::ReferableUri
        if self.#{f} && attributes[:referable_type] == "Skyline::ReferableUri"
          self.#{f}.referable.reload if self.#{f}.referable
          self.#{f}.referable ||= attributes[:referable_type].constantize.new
        
          if referable_params.kind_of?(Hash)
            referable_params.each do |k, v|
              self.#{f}.send(k.to_s + "=", v) if self.#{f}.respond_to?(k.to_s + "=")
            end
          end
        end
      end          
    END
  end
end