trabajo-afectivo/lib/models.rb

221 lines
5.7 KiB
Ruby
Raw Normal View History

class Models
include ApplicationLib
=begin
get list of models
result = Models.all
returns
{
'Some::Classname1' => {
attributes: ['id', 'name', '...']
reflections: ...model.reflections...
},
'Some::Classname2' => {
attributes: ['id', 'name', '...']
reflections: ...model.reflections...
},
}
=end
def self.all
all = {}
dir = "#{Rails.root}/app/models/"
Dir.glob( "#{dir}**/*.rb" ) do |entry|
next if entry =~ /application_model/i
next if entry =~ %r{channel/}i
next if entry =~ %r{observer/}i
next if entry =~ %r{store/provider/}i
entry.gsub!(dir, '')
entry = entry.to_classname
model_class = load_adapter(entry)
next if !model_class
next if !model_class.respond_to? :new
model_object = model_class.new
next if !model_object.respond_to? :attributes
all[model_class] = {}
all[model_class][:attributes] = model_class.attribute_names
all[model_class][:reflections] = model_class.reflections
2015-07-06 00:33:43 +00:00
#puts model_class
#puts "rrrr #{all[model_class][:attributes]}"
2015-07-06 00:33:43 +00:00
#puts " #{model_class.attribute_names.inspect}"
end
all
end
=begin
get reference list of a models
result = Models.references('User', 2)
returns
{
'Some::Classname1' => {
2015-07-06 00:33:43 +00:00
attribute1: 12,
attribute2: 6,
},
'Some::Classname2' => {
2015-07-06 00:33:43 +00:00
updated_by_id: 12,
created_by_id: 6,
},
}
=end
def self.references(object_name, object_id)
2015-07-06 00:33:43 +00:00
# check if model exists
object_model = load_adapter(object_name)
object_model.find(object_id)
2015-07-06 00:33:43 +00:00
list = all
2015-07-06 00:33:43 +00:00
references = {}
# find relations via attributes
2015-07-06 00:33:43 +00:00
ref_attributes = ["#{object_name.downcase}_id"]
# for users we do not define relations for created_by_id &
# updated_by_id - add it here directly
if object_name == 'User'
ref_attributes.push 'created_by_id'
ref_attributes.push 'updated_by_id'
end
list.each {|model_class, model_attributes|
2015-07-06 00:33:43 +00:00
if !references[model_class.to_s]
references[model_class.to_s] = {}
end
2015-07-03 16:51:22 +00:00
2015-07-06 00:33:43 +00:00
next if !model_attributes[:attributes]
ref_attributes.each {|item|
2015-07-03 16:51:22 +00:00
next if !model_attributes[:attributes].include?(item)
count = model_class.where("#{item} = ?", object_id).count
next if count == 0
2015-07-06 00:33:43 +00:00
if !references[model_class.to_s][item]
references[model_class.to_s][item] = 0
end
2015-07-03 16:51:22 +00:00
Rails.logger.debug "FOUND (by id) #{model_class}->#{item} #{count}!"
2015-07-06 00:33:43 +00:00
references[model_class.to_s][item] += count
}
}
# find relations via reflections
list.each {|model_class, model_attributes|
next if !model_attributes[:reflections]
model_attributes[:reflections].each {|_reflection_key, reflection_value|
2015-07-03 16:51:22 +00:00
next if reflection_value.macro != :belongs_to
2015-07-06 00:33:43 +00:00
col_name = "#{reflection_value.name}_id"
next if ref_attributes.include?(col_name)
2015-07-03 16:51:22 +00:00
if reflection_value.options[:class_name] == object_name
2015-07-06 00:33:43 +00:00
count = model_class.where("#{col_name} = ?", object_id).count
2015-06-30 22:23:18 +00:00
next if count == 0
2015-07-06 00:33:43 +00:00
if !references[model_class.to_s][col_name]
references[model_class.to_s][col_name] = 0
end
Rails.logger.debug "FOUND (by ref without class) #{model_class}->#{col_name} #{count}!"
references[model_class.to_s][col_name] += count
end
2015-07-03 16:51:22 +00:00
next if reflection_value.options[:class_name]
next if reflection_value.name != object_name.downcase.to_sym
2015-07-06 00:33:43 +00:00
count = model_class.where("#{col_name} = ?", object_id).count
2015-07-03 16:51:22 +00:00
next if count == 0
2015-07-06 00:33:43 +00:00
if !references[model_class.to_s][col_name]
references[model_class.to_s][col_name] = 0
end
Rails.logger.debug "FOUND (by ref with class) #{model_class}->#{col_name} #{count}!"
references[model_class.to_s][col_name] += count
}
}
2015-07-06 00:33:43 +00:00
# cleanup, remove models with empty references
references.each {|k, v|
next if !v.empty?
references.delete(k)
}
2015-07-06 00:33:43 +00:00
references
end
2015-07-06 00:33:43 +00:00
=begin
get reference total of a models
count = Models.references_total('User', 2)
returns
count # 1234
=end
def self.references_total(object_name, object_id)
2015-07-06 01:12:36 +00:00
references = references(object_name, object_id)
2015-07-06 00:33:43 +00:00
total = 0
references.each {|_model, model_references|
model_references.each {|_col, count|
total += count
}
}
total
end
=begin
merge model references to other model
result = Models.merge('User', 2, 4711) # Object, object_id_of_primary, object_id_which_should_be_merged
2015-07-06 00:33:43 +00:00
returns
true # false
=end
def self.merge(object_name, object_id_primary, object_id_to_merge, force = false)
# if lower x references to update, do it right now
if force
2015-07-06 01:12:36 +00:00
total = references_total(object_name, object_id_to_merge)
2015-07-06 00:33:43 +00:00
if total > 1000
fail "Can't merge object because object has more then 1000 (#{total}) references, please contact your system administrator."
end
end
2015-07-06 01:12:36 +00:00
# update references
references = references(object_name, object_id_to_merge)
2015-07-06 00:33:43 +00:00
references.each {|model, attributes|
model_object = Object.const_get(model)
2015-07-06 01:12:36 +00:00
# collect items and attributes to update
2015-07-06 00:33:43 +00:00
items_to_update = {}
attributes.each {|attribute, _count|
2015-07-06 01:12:36 +00:00
Rails.logger.debug "#{object_name}: #{model}.#{attribute}->#{object_id_to_merge}->#{object_id_primary}"
2015-07-06 00:33:43 +00:00
model_object.where("#{attribute} = ?", object_id_to_merge).each {|item|
if !items_to_update[item.id]
items_to_update[item.id] = item
end
items_to_update[item.id][attribute.to_sym] = object_id_primary
}
}
2015-07-06 01:12:36 +00:00
# update items
ActiveRecord::Base.transaction do
items_to_update.each {|_id, item|
item.save
}
end
2015-07-06 00:33:43 +00:00
}
true
end
end