Permalink
Browse files

ONE BIG COMMIT (it is bad, very bad)

  • Loading branch information...
1 parent eecbdcc commit 83f815daffdf884090d2bba56bda2b80b2ff47a3 DanielVartanov committed May 20, 2010
View
@@ -19,45 +19,51 @@ def to_atom(params=nil)
params ||= {}
maximum_precedence = (!params[:precedence].blank? ? params[:precedence].to_i : 100)
included = params[:include].to_s.split(',')
- expand = (included.include?('$children') ? :all : :immediate_children)
+ selected = params[:select].to_s.split(',') + ['_root']
+ expand = (included.include?('$children') ? :all_children : :immediate_children)
returning Atom::Entry.new do |entry|
-
- entry.id = self.sdata_resource_url
- entry.title = entry_title
- entry.updated = self.updated_at
- entry.authors << Atom::Person.new(:name => self.respond_to?('author') ? self.author : sdata_default_author)
- entry.links << Atom::Link.new(:rel => 'self',
- :href => self.sdata_resource_url,
- :type => 'applicaton/atom+xml; type=entry',
- :title => 'Refresh')
- entry.categories << Atom::Category.new(:scheme => 'http://schemas.sage.com/sdata/categories',
+ entry.id = self.sdata_resource_url
+ entry.title = entry_title
+ entry.updated = self.updated_at
+ entry.authors << Atom::Person.new(:name => self.respond_to?('author') ? self.author : sdata_default_author)
+ entry.links << Atom::Link.new(:rel => 'self',
+ :href => self.sdata_resource_url,
+ :type => 'applicaton/atom+xml; type=entry',
+ :title => 'Refresh')
+ entry.categories << Atom::Category.new(:scheme => 'http://schemas.sage.com/sdata/categories',
:term => 'resource',
:label => 'Resource')
-
- if maximum_precedence > 0
- #raise 'entry-level error'
- begin
- entry.payload = Atom::Content::Payload.new(self.payload(self.sdata_node_name, self, expand, included, 1, maximum_precedence))
- rescue Exception => e
- entry.diagnosis = Atom::Content::Diagnosis.new(ApplicationDiagnosis.new(:exception => e).to_xml(:entry))
- end
+ if maximum_precedence > 0
+ begin
+ entry.payload = Atom::Content::Payload.new(Payload.generate(self.sdata_node_name, self, expand, included, selected, 1, maximum_precedence, nil))
+ rescue Exception => e
+ entry.diagnosis = Atom::Content::Diagnosis.new(ApplicationDiagnosis.new(:exception => e).to_xml(:entry))
end
- entry.content = sdata_content
-
+ end
+ entry.content = sdata_content
end
end
- protected
+ def sdata_node_name(entity=self.class)
+ entity.to_s.demodulize.camelize(:lower)
+ end
- def sdata_default_author
- "Billing Boss"
+ def resource_header_attributes(resource, included)
+ hash = {}
+ hash.merge!({"xlmns:sdata:key" => resource.id, "xlmns:sdata:url" => resource.sdata_resource_url}) if resource.id
+ hash.merge!("xlmns:sdata:descriptor" => resource.entry_content) if included.include?("$descriptor")
+ hash.merge!("xlmns:sdata:uuid" => resource.uuid.to_s) if resource.respond_to?("uuid") && !resource.uuid.blank?
+ hash
end
- def sdata_resource_url()
+
+ def sdata_resource_url
$APPLICATION_URL + $SDATA_STORE_PATH + sdata_node_name.pluralize + "('#{self.id}')"
end
- def sdata_collection_url(parent, id, child)
- $APPLICATION_URL + $SDATA_STORE_PATH + parent.camelize(:lower) + "('#{id}')/" + child
+ protected
+
+ def sdata_default_author
+ "Billing Boss"
end
def entry_title
@@ -77,66 +83,11 @@ def entry_content
def default_entry_content
self.class.name
end
-
- def xmlns_qualifier_for(element)
- "xmlns:crmErp:#{element}"
- end
-
- def sdata_node_name(entity=self.class)
- entity.to_s.demodulize.camelize(:lower)
- end
-
- def resource_header_attributes(resource, included)
- hash = {"xlmns:sdata:key" => resource.id, "xlmns:sdata:url" => resource.sdata_resource_url}
- hash.merge!("xlmns:sdata:descriptor" => resource.entry_content) if included.include?("$descriptor")
- hash.merge!("xlmns:sdata:uuid" => resource.uuid.to_s) if resource.respond_to?("uuid") && !resource.uuid.blank?
- hash
- end
- def payload(node_name, node_value, expand, included, element_precedence, maximum_precedence, resource_collection=nil)
- return "" if element_precedence > maximum_precedence
- builder = Builder::XmlMarkup.new
- if node_value.respond_to?('payload_map')
- builder.__send__(node_value.xmlns_qualifier_for(node_name), resource_header_attributes(node_value, included)) do |element|
- if (expand != :none) || included.include?(node_name.to_s.camelize(:lower))
- node_value.payload_map.each_pair do |child_node_name, child_node_data|
- expand = :none if (expand == :immediate_children)
- element << node_value.payload(child_node_name.to_s.camelize(:lower), child_node_data[:value], expand, included, child_node_data[:precedence], maximum_precedence, child_node_data[:resource_collection])
- end
- end
- end
- elsif node_value.is_a?(Array)
- if resource_collection
- scoped_children_collection = sdata_collection_url(resource_collection[:parent], self.id, resource_collection[:url])
- builder.__send__(xmlns_qualifier_for(node_name), {"xlmns:sdata:url" => scoped_children_collection}) do |element|
- if (expand != :none) || included.include?(node_name.to_s.camelize(:lower))
- expand = :none if (expand == :immediate_children)
- node_value.each do |item|
- element << self.payload(node_name.to_s.singularize.camelize(:lower), item, expand, included, element_precedence, maximum_precedence)
- end
- end
- end
- else
- builder.__send__(xmlns_qualifier_for(node_name)) do |element|
- expand = :none if (expand == :immediate_children)
- node_value.each do |item|
- element << self.payload(node_name.to_s.singularize, item, expand, included, element_precedence, maximum_precedence, (item.is_a?(Hash) ? item[:resource_collection] : nil))
- end
- end
- end
- elsif node_value.is_a?(Hash)
- builder.__send__(xmlns_qualifier_for(node_name)) do |element|
- expand = :none if (expand == :immediate_children)
- node_value.each_pair do |child_node_name, child_node_data|
- element << self.payload(child_node_name.to_s.camelize(:lower), child_node_data, expand, included, element_precedence, maximum_precedence, (child_node_data.is_a?(Hash) ? child_node_data[:resource_collection] : nil))
- end
- end
- else
- builder.__send__(xmlns_qualifier_for(node_name.to_s.camelize(:lower)), (node_value ? node_value.to_s : {'xlmns:xsi:nil' => "true"}))
- end
- end
-
end
end
end
-ActiveRecord::Base.extend SData::ActiveRecordMixin
+# Extension of ActiveRecord removed due to refactoring. Now VirtualBase is extended instead.
+# Not sure yet if there is a case where we DO need to extend ActiveRecord directly.
+# Might considering merging those two classes otherwise.
+# RADAR: Tested refactoring, but it could still be buggy if I missed something! Watch out.
View
@@ -29,6 +29,7 @@ def sdata_collection
populate_open_search_for(collection)
build_feed_links_for(collection)
render :xml => collection, :content_type => "application/atom+xml; type=feed"
+
rescue Exception => e
render :xml => ApplicationDiagnosis.new(:exception => e).to_xml(:root)
end
@@ -162,10 +163,8 @@ def sdata_scope
if sdata_options[:scoping]
options[:conditions] ||= []
sdata_options[:scoping].each do |scope|
- scopable = self.send(scope[:object])
- conditions = ["#{scope[:attribute]} = ?", scopable.send(scope[:key])]
- options[:conditions][0] = [options[:conditions].to_a[0], conditions[0]].compact.join(' and ')
- options[:conditions] << conditions[1].to_s
+ options[:conditions][0] = [options[:conditions].to_a[0], scope].compact.join(' and ')
+ options[:conditions] << current_user.id.to_s
end
end
@@ -181,6 +180,7 @@ def sdata_scope
#if user has hundreds of records but requests first 10, we shouldnt load them all into memory
#but use sql query to count how many exist in total, and then load the first 10 only
+ #FIXME: do not return records deleted through acts_as_paranoid!
results = sdata_options[:model].all(options)
@total_results = results.count
paginated_results = results[zero_based_start_index,records_to_return]
@@ -200,4 +200,4 @@ def populate_open_search_for(feed)
end
end
-ActionController::Base.extend SData::ControllerMixin
+ActionController::Base.extend SData::ControllerMixin
View
@@ -53,7 +53,7 @@ def diagnosis_payload
value = self.send(attribute) unless [:http_status_code].include?(attribute)
if value
if value.is_a?(Exception)
- node << (XML::Node.new("sdata:stackTrace") << value.backtrace) if !['production', 'staging'].include?(ENV['RAILS_ENV'])
+ node << (XML::Node.new("sdata:stackTrace") << value.backtrace.join("\n") ) if !['production', 'staging'].include?(ENV['RAILS_ENV'])
else
node << (XML::Node.new("sdata:#{attribute.to_s.camelize(:lower)}") << value)
end
@@ -139,8 +139,8 @@ module SDataRescue
#TODO: rescue_action_in_public won't work for some reason here. When merging with real Billing Boss app,
#investigate. Need to preserve stack traces for dev env for non-simply requests.
def sdata_global_rescue(exception, request_path)
- error_payload = case exception.class.to_s
- when "NoMethodError"
+ error_payload = case exception.class.to_s.demodulize
+ when 'NoMethodError'
if request_path.match /^\/sdata\/#{$SDATA_HIERARCHY[0]}\/#{$SDATA_HIERARCHY[1]}\/#{$SDATA_HIERARCHY[2]}\/[A-z]+\/.*/
SData::ApplicationDiagnosis.new(:exception => exception, :http_status_code => '500')
elsif request_path.match /^\/sdata\/#{$SDATA_HIERARCHY[0]}\/#{$SDATA_HIERARCHY[1]}\/#{$SDATA_HIERARCHY[2]}\/[A-z]+/
@@ -158,7 +158,8 @@ def sdata_global_rescue(exception, request_path)
else
SData::ApplicationNotFound.new(:exception => exception, :http_status_code => '404')
end
- #TODO: customize further as needed
+ when 'AccessDeniedException'
+ SData::ApplicationDiagnosis.new(:exception => exception, :http_status_code => '403')
else
SData::ApplicationDiagnosis.new(:exception => exception, :http_status_code => '500')
end
@@ -167,4 +168,4 @@ def sdata_global_rescue(exception, request_path)
end
end
end
-ActionController::Base.extend SData::ApplicationControllerMixin
+ActionController::Base.extend SData::ApplicationControllerMixin
View
@@ -0,0 +1,111 @@
+class Payload
+
+ # FIXME: temporary
+ # is_sync? should be passed as param to generate, and should be true if feed is a synch feed.
+ # In this case, ?include will show only links and not embedded data for associations,
+ # while ?include=$children will be implied
+ def self.is_sync?
+ false
+ end
+
+ def self.generate(*params)
+ node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection = *params
+ expand = :all_children if is_sync?
+ return "" if element_precedence > maximum_precedence
+ return "" if self.excluded_in_select?(node_name, selected)
+ builder = Builder::XmlMarkup.new
+ if node_value.respond_to?('payload_map')
+ self.construct_from_sdata_model(*params)
+ elsif node_value.is_a?(Array)
+ self.construct_from_array(*params)
+ elsif node_value.is_a?(Hash)
+ self.construct_from_hash(*params)
+ else
+ self.construct_from_string(*params)
+ end
+ end
+
+ def self.construct_from_sdata_model(node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection=nil)
+ builder = Builder::XmlMarkup.new
+ builder.__send__(self.xmlns_qualifier_for(node_name), node_value.resource_header_attributes(node_value, included)) do |element|
+ if (expand != :none) || included.include?(node_name.to_s.camelize(:lower))
+ expand = :none if (expand == :immediate_children)
+ node_value.payload_map.each_pair do |child_node_name, child_node_data|
+ if child_node_data[:type] == :association
+ child_expand = :none
+ else
+ child_expand = expand
+ end
+ element << self.generate(child_node_name.to_s.camelize(:lower), child_node_data[:value], child_expand, included, selected, child_node_data[:precedence], maximum_precedence, child_node_data[:resource_collection])
+ end
+ end
+ end
+ end
+
+ def self.construct_from_array(*params)
+ builder = Builder::XmlMarkup.new
+ if params[7] #resource_collection
+ self.construct_from_sdata_array(*params)
+ else
+ self.construct_from_non_sdata_array(*params)
+ end
+ end
+
+ def self.construct_from_sdata_array(node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection)
+ builder = Builder::XmlMarkup.new
+ scoped_children_collection = self.sdata_collection_url(resource_collection[:parent], resource_collection[:url])
+ builder.__send__(self.xmlns_qualifier_for(node_name), {"xlmns:sdata:url" => scoped_children_collection}) do |element|
+ if (expand != :none || included.include?(node_name.to_s.camelize(:lower)))
+ expand = :immediate_children if (expand == :none && included.include?(node_name.to_s.camelize(:lower))) && !is_sync?
+ node_value.each do |item|
+ element << self.generate(item.sdata_node_name, item, expand, included, selected, element_precedence, maximum_precedence, nil)
+ end
+ end
+ end
+ end
+
+ def self.construct_from_non_sdata_array(node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection)
+ builder = Builder::XmlMarkup.new
+ builder.__send__(xmlns_qualifier_for(node_name)) do |element|
+ expand = :immediate_children if expand == :none
+ node_value.each do |item|
+ element << self.generate(node_name.to_s.singularize, item, expand, included, selected, element_precedence, maximum_precedence, (item.is_a?(Hash) ? item[:resource_collection] : nil))
+ end
+ end
+ end
+
+ def self.construct_from_hash(node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection)
+ builder = Builder::XmlMarkup.new
+ builder.__send__(xmlns_qualifier_for(node_name)) do |element|
+ expand = :none if (expand == :immediate_children)
+ node_value.each_pair do |child_node_name, child_node_data|
+ element << self.generate(child_node_name.to_s.camelize(:lower), child_node_data, expand, included, selected, element_precedence, maximum_precedence, (child_node_data.is_a?(Hash) ? child_node_data[:resource_collection] : nil))
+ end
+ end
+ end
+
+ def self.construct_from_string(node_name, node_value, expand, included, selected, element_precedence, maximum_precedence, resource_collection)
+ builder = Builder::XmlMarkup.new
+ builder.__send__(self.xmlns_qualifier_for(node_name.to_s.camelize(:lower)), (node_value ? node_value.to_s : {'xlmns:xsi:nil' => "true"}))
+ end
+
+ def self.xmlns_qualifier_for(element)
+ "xmlns:crmErp:#{element}"
+ end
+
+ def self.sdata_collection_url(parent, child)
+ $APPLICATION_URL + $SDATA_STORE_PATH + parent.sdata_node_name + "('#{parent.id}')/" + child
+ end
+
+ def self.excluded_in_select?(node_name, selected)
+ if selected.empty?
+ return false
+ elsif selected.include?('_root')
+ selected.delete '_root'
+ return false
+ else
+ return !selected.include?(node_name.to_s.camelize(:lower))
+ end
+ end
+
+end
View
@@ -0,0 +1,54 @@
+# Tried using ActiveRecord::BaseWithoutTable, but had problems calling __include__ on it.
+# Research if we need features provided by BWT, otherwise use this.
+
+require 'forwardable'
+
+class VirtualBase
+ extend Forwardable
+ attr_accessor :baze
+ def_delegators :baze, :id, :created_at, :updated_at, :save, :update_attributes
+
+ def initialize(the_baze, the_type=nil)
+ self.baze = the_baze
+
+ if self.respond_to?('sdata_type') && the_type
+ self.sdata_type = the_type
+ end
+
+ super()
+ end
+
+ def self.build_for(data, the_type=nil)
+ if data.is_a? Array
+ array = []
+ data.each do |item|
+ array << self.new(item, the_type) if item
+ end
+ array
+ else
+ data ? self.new(data, the_type) : nil
+ end
+ end
+
+ # FIXME: Below methods transfer ActiveRecord methods to the baze. Is there a cleaner way to do this?
+
+ def self.find(*params)
+ self.new(self.baze_class.find(*params))
+ end
+
+ def self.first(*params)
+ self.new(self.baze_class.first(*params))
+ end
+
+ def self.all(*params)
+ virtual_results = []
+ results = self.baze_class.all(*params)
+ results.each do |result|
+ virtual_results << self.new(result)
+ end
+ virtual_results
+ end
+end
+
+
+VirtualBase.extend SData::ActiveRecordMixin
Oops, something went wrong.

0 comments on commit 83f815d

Please sign in to comment.