class Netfira::WebConnect::Model::Relation
Attributes
Public Class Methods
for(class_a, class_b)
click to toggle source
# File lib/netfira/web_connect/model/relation.rb, line 123 def for(class_a, class_b) name = [class_a, class_b].map{ |c| (c.is_a?(Class) ? c : c.class).name.demodulize }.sort.join 'To' Models.const_get name if Models.const_defined? name end
for!(*args)
click to toggle source
# File lib/netfira/web_connect/model/relation.rb, line 128 def for!(*args) self.for(*args).tap do |result| raise args.map { |c| (Class === c ? c : c.class).name.demodulize.pluralize }.join ' are not related to ' unless result end end
materialize(name_a, name_b)
click to toggle source
# File lib/netfira/web_connect/model/relation.rb, line 11 def materialize(name_a, name_b) # The new class, e.g. Models::ImageToProduct klass = Class.new(self) Models.const_set "#{name_a}To#{name_b}", klass # An array of related classes, e.g. [Models::Image, Models::Product] klass.related_classes = [name_a, name_b].map{ |n| Models.const_get n.camelize.singularize } # Sets up paranoia, including a with_deleted scope for consistency if Netfira::WebConnect.paranoia? klass.acts_as_paranoid else def klass.with_deleted; self end end # Enables finding by origin IDs, e.g.: # ImageToProduct.find_by_origin_ids(image: 'apple.jpg', product: 'apple', shop: 5) find_by_origin_ids = proc do |**args| # The table of the current class, e.g. nf_images_to_products join_table = klass.arel_table # The scope we're building scope = klass # Include a shop in the scope if one is given shop = args[:shop] if shop shop = shop.id if Models::Shop === shop raise "`shop` must be an integer or an instance of #{Models::Shop.name}" unless Fixnum === shop end # Join each class and add where clauses klass.related_classes.each do |related_class| # The related table, e.g. nf_images related_table = related_class.arel_table # The argument expected to identify the relevant row of the table, e.g. :image origin_id_arg = related_class.single_name.to_sym # The origin ID to find in the table, e.g. 'apple.jpg' origin_id = args[origin_id_arg] or raise "Missing argument `#{origin_id_arg}`" # The column of the related table in which to seek the origin ID, e.g. :file_name origin_key = related_class.origin_key.to_sym # The column on which to join the relation table, e.g. :image_id join_key = :"#{related_class.single_name}_id" # Join the related table, e.g.: # INNER JOIN "nf_images" ON "nf_images_to_products"."image_id" = "nf_images"."id" scope = scope.joins join_table.join(related_table).on(join_table[join_key].eq related_table[:id]).join_sql # Look for the origin ID, e.g.: # WHERE "nf_images"."file_name" = 'apple.jpg' scope = scope.where related_table[origin_key].eq origin_id # Limit to the given shop, e.g.: # AND "nf_images"."shop_id" = 5 scope = scope.where related_table[:shop_id].eq shop if shop end # Only look for one record. scope.limit 1 end klass.scope :find_by_origin_ids, find_by_origin_ids end
table_name()
click to toggle source
# File lib/netfira/web_connect/model/relation.rb, line 115 def table_name @table_name ||= if self == Model::Relation Models::Table.table_name else Netfira::WebConnect.db_table_prefix(related_classes.map(&:plural_name).join '_to_').to_s end end
Public Instance Methods
records()
click to toggle source
# File lib/netfira/web_connect/model/relation.rb, line 136 def records self.class.current_scope = nil if Netfira::WebConnect.paranoia? # Fixes a bug triggered by paranoia self.class.related_classes.map{ |klass| __send__ klass.single_name.to_sym } end