root/trunk/app/models/node.rb @ 114

Revision 114, 6.1 KB (checked in by mauriciobomfim, 4 years ago)

Implemented refresh_cache of nodes in case of changes on NodeLinks?.

Line 
1require 'model_helper'
2require 'node_link_association'
3require 'anchor'
4require 'nav_attribute'
5
6class Node < AbstractModel
7  include InheritanceCollector
8
9  property :created_at, "Time"
10  property :updated_at, "Time"
11     
12  has_many :links, :class_name => "NodeLink", :dependent => true, :order => "type, position"
13  has_many :link_references, :class_name => "NodeLink", :foreign_key => "target_node_id", :dependent => true, :order => "type, position"
14
15  attr_accessor :container
16 
17        after_update :refresh_cache
18        after_create :refresh_cache
19        after_save :refresh_cache
20        after_destroy :refresh_cache
21       
22        @@find_cache = {}
23               
24  def Node.refresh_cache     
25    @@find_cache = {}
26  end
27   
28                def refresh_cache
29                        Node.refresh_cache
30                end
31               
32                class << self
33               
34                        def find_by_sql(sql, raw_records = false)                         
35                                sql = sanitize_sql(sql)
36                                sql_hash = MD5.hexdigest(sql + raw_records.to_s)
37                               
38                                unless @@find_cache[sql_hash].nil?
39                                        return @@find_cache[sql_hash]
40                                end
41                               
42                                records = connection.select(sql)
43                                if raw_records then
44                                        records = records
45                                else 
46                                        records = records.inject([]) { |objects, record| objects << instantiate(record) }
47                                end
48                                @@find_cache[sql_hash] = records
49                                records
50                        end
51               
52                end
53       
54       
55        def self.reset_nav_classes_cache
56    @@nav_classes = nil
57    @@nav_attributes = nil
58  end
59   
60  def nav_class
61    @@nav_classes ||= {}
62    if @@nav_classes.include?(self.class.name)
63      return @@nav_classes[self.class.name]
64    else
65      return refresh_nav_class
66    end
67  end 
68
69  def nav_attributes
70    @@nav_attributes ||= {}
71    if @@nav_attributes.include?(self.class.name)
72      return @@nav_attributes[self.class.name]
73    else
74      return refresh_nav_attributes
75    end
76  end
77           
78  def refresh_nav_class
79    nc = NavClass.find_first ["name = ?", self.class.name]
80    @@nav_classes[self.class.name] = nc
81  end   
82
83  def refresh_nav_attributes
84    na = attribute_collect(nav_class).inject({}) do |hash, attr|
85      hash[attr.name] = attr
86      hash
87    end
88    @@nav_attributes[self.class.name] = na
89  end
90 
91  def after_save
92    after_node_save
93  end
94
95  def after_node_save() end
96
97  def after_destroy
98    NodeLink.destroy_all ["node_id = ? OR target_node_id = ?", self.id, self.id]
99    after_node_delete
100  end
101
102  def after_node_delete() end
103 
104  def label
105    if nav_class.label_attribute?
106      read_attribute(nav_class.label_attribute).to_s rescue id.to_s
107    else
108      id.to_s
109    end       
110  end
111   
112  def nav_operations
113    @nav_operations ||= read_nav_operations
114  end
115 
116  def read_nav_operations
117    ops = operation_collect(nav_class)
118    ops = ops.inject({}) { |hash, op| hash[op.name] = op; hash }
119  end
120
121  def method_missing(method_id, *arguments)
122    method_name = method_id.id2name
123     
124    if method_name =~ read_method?
125      return read_attribute($1) if nav_attributes.include?($1)
126      return read_link($1) if node_links.include?($1)
127      return do_operation($1, *arguments) if nav_operations.include?($1)
128      super
129    elsif method_name =~ query_method?
130      return query_attribute($1) if nav_attributes.include?($1)
131      return query_link($1) if node_links.include?($1)
132      super
133    else
134      super
135    end
136  end
137
138  def do_operation(op_name, *arguments)
139    op = nav_operations[op_name]
140    code = op.code
141    params = op.params if op.params && !op.params.empty?
142
143    begin   
144      buffer = <<-EOS
145        def self.#{op_name}(context = nil, controller = nil #{params ? ',' + params : ''})
146          #{code}
147        end
148      EOS
149      instance_eval(buffer, op_name, 0)
150      ret = send(op_name, *arguments)
151    rescue => ex
152      ln = -1
153      buffer_with_ln = buffer.split("\n").map { |line| ln += 1; "#{ln}:#{line}" }.join("\n")
154      err_buffer = "ERROR on trying operation #{op_name}...\nSOURCE CODE:\n#{buffer_with_ln}\nMESSAGE: #{ex.message}\nSTACK TRACE:\n#{ex.backtrace.join("\n")}"
155      logger.info err_buffer
156      $stdout.puts err_buffer     
157      raise
158    end
159    ret
160  end
161 
162  def node_links
163    @node_links ||= load_links
164  end
165
166  def load_links
167    node_links = {}
168    for l in (nav_class.links_all)
169      k = l.name.underscore
170      node_links[k] = { :link => l, :nodes => nil }
171    end
172    node_links
173  end 
174
175  def read_link(name)
176    return nil if node_links[name].nil?                     
177    sql = %{ {link} sr:target_node_id {id}; rdf:type {?};
178              sr:node_id {?}; [ sr:position {node_link_position} ] } 
179    link = node_links[name][:link]                     
180    nodes = node_links[name][:nodes]
181    if nodes.nil?
182      target_klass = Object.const_get(link.target_nav_class.name)
183      nodes = target_klass.find_all nil, "node_link_position", 
184                                    nil, [sql, link.name.to_uri, self.id] 
185      nodes.extend(NodeLinkAssociation)
186      nodes.parent_node = self
187      nodes.link_type = link.name
188      node_links[name][:nodes] = nodes
189    end
190    return nodes
191  end
192
193  def query_link(name)
194    node_links.include?(name)
195  end
196
197  def query_attribute(name)
198    not read_attribute(name).nil?
199  end
200 
201  def read_attribute(attr_name)
202    val = super(attr_name)
203    if val.nil?
204      begin 
205        attr_def = nav_attributes[attr_name]
206        case attr_def
207          when IndexNavAttribute
208            val = Index.find(attr_def.index.id)
209            params_values = instance_eval(attr_def.params) if attr_def.params?
210            val.entries(params_values)
211            val.container = self
212          when ContextAnchorNavAttribute
213            val = ContextAnchorValue.new(self, attr_def)
214            val.container = self
215          when IndexAnchorNavAttribute
216            val = IndexAnchorValue.new(self, attr_def)
217            val.container = self
218          when ComputedNavAttribute
219            val = instance_eval(attr_def.code) rescue nil       
220          else
221            val = nil
222        end
223      rescue => ex
224        logger.error ex.inspect
225        raise "Could not read '#{self.class.name}##{attr_name}' value for node '#{self.id}'\n#{ex}."
226      end
227    end
228    val
229  end
230   
231end
Note: See TracBrowser for help on using the browser.