Improved model helpers.

This commit is contained in:
Martin Edenhofer 2015-07-06 02:33:43 +02:00
parent 359f276c87
commit 54f11be47b
2 changed files with 211 additions and 30 deletions

View file

@ -40,9 +40,9 @@ returns
all[model_class] = {} all[model_class] = {}
all[model_class][:attributes] = model_class.attribute_names all[model_class][:attributes] = model_class.attribute_names
all[model_class][:reflections] = model_class.reflections all[model_class][:reflections] = model_class.reflections
#puts model_class
#puts "rrrr #{all[model_class][:attributes]}" #puts "rrrr #{all[model_class][:attributes]}"
#puts model.class #puts " #{model_class.attribute_names.inspect}"
#puts " #{model.attribute_names.inspect}"
end end
all all
end end
@ -57,38 +57,51 @@ returns
{ {
'Some::Classname1' => { 'Some::Classname1' => {
attributes: ['id', 'name', '...'] attribute1: 12,
reflections: ...model.reflections... attribute2: 6,
}, },
'Some::Classname2' => { 'Some::Classname2' => {
attributes: ['id', 'name', '...'] updated_by_id: 12,
reflections: ...model.reflections... created_by_id: 6,
}, },
} }
=end =end
def self.references(object_name, object_id) def self.references(object_name, object_id)
# check if model exists
object_model = load_adapter(object_name) object_model = load_adapter(object_name)
object_model.find(object_id) object_model.find(object_id)
list = all list = all
references = { references = {}
model: {},
total: 0,
}
# find relations via attributes # find relations via attributes
list.each {|model_class, model_attributes| ref_attributes = ["#{object_name.downcase}_id"]
references[:model][model_class.to_s] = 0
next if !model_attributes[:attributes]
%w(created_by_id updated_by_id).each {|item|
# 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|
if !references[model_class.to_s]
references[model_class.to_s] = {}
end
next if !model_attributes[:attributes]
ref_attributes.each {|item|
next if !model_attributes[:attributes].include?(item) next if !model_attributes[:attributes].include?(item)
count = model_class.where("#{item} = ?", object_id).count count = model_class.where("#{item} = ?", object_id).count
next if count == 0 next if count == 0
if !references[model_class.to_s][item]
references[model_class.to_s][item] = 0
end
Rails.logger.debug "FOUND (by id) #{model_class}->#{item} #{count}!" Rails.logger.debug "FOUND (by id) #{model_class}->#{item} #{count}!"
references[:model][model_class.to_s] += count references[model_class.to_s][item] += count
} }
} }
@ -98,30 +111,103 @@ returns
model_attributes[:reflections].each {|_reflection_key, reflection_value| model_attributes[:reflections].each {|_reflection_key, reflection_value|
next if reflection_value.macro != :belongs_to next if reflection_value.macro != :belongs_to
col_name = "#{reflection_value.name}_id"
next if ref_attributes.include?(col_name)
if reflection_value.options[:class_name] == object_name if reflection_value.options[:class_name] == object_name
count = model_class.where("#{reflection_value.name}_id = ?", object_id).count count = model_class.where("#{col_name} = ?", object_id).count
next if count == 0 next if count == 0
Rails.logger.debug "FOUND (by ref without class) #{model_class}->#{reflection_value.name} #{count}!" if !references[model_class.to_s][col_name]
references[:model][model_class.to_s] += count 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 end
next if reflection_value.options[:class_name] next if reflection_value.options[:class_name]
next if reflection_value.name != object_name.downcase.to_sym next if reflection_value.name != object_name.downcase.to_sym
count = model_class.where("#{reflection_value.name}_id = ?", object_id).count count = model_class.where("#{col_name} = ?", object_id).count
next if count == 0 next if count == 0
if !references[model_class.to_s][col_name]
Rails.logger.debug "FOUND (by ref with class) #{model_class}->#{reflection_value.name} #{count}!" references[model_class.to_s][col_name] = 0
references[:model][model_class.to_s] += count end
Rails.logger.debug "FOUND (by ref with class) #{model_class}->#{col_name} #{count}!"
references[model_class.to_s][col_name] += count
} }
} }
references[:model].each {|_k, v| # cleanup, remove models with empty references
next if v == 0 references.each {|k, v|
references[:total] += v next if !v.empty?
references.delete(k)
} }
references references
end end
=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)
references = self.references(object_name, object_id)
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)
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
total = Models.references_total(object_name, object_id_to_merge)
if total > 1000
fail "Can't merge object because object has more then 1000 (#{total}) references, please contact your system administrator."
end
end
references = Models.references(object_name, object_id_to_merge)
references.each {|model, attributes|
model_object = Object.const_get(model)
items_to_update = {}
attributes.each {|attribute, _count|
#puts "-> #{model}: #{attribute}->#{object_id_to_merge}->#{object_id_primary}"
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
}
}
items_to_update.each {|_id, item|
item.save
}
}
true
end
end end

View file

@ -20,6 +20,19 @@ class ModelTest < ActiveSupport::TestCase
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1, created_by_id: 1,
) )
agent2 = User.create_or_update(
login: 'model-agent2@example.com',
firstname: 'Model',
lastname: 'Agent2',
email: 'model-agent2@example.com',
password: 'agentpw',
active: true,
roles: roles,
groups: groups,
updated_at: '2015-02-05 17:37:00',
updated_by_id: agent1.id,
created_by_id: 1,
)
organization1 = Organization.create_if_not_exists( organization1 = Organization.create_if_not_exists(
name: 'Model Org 1', name: 'Model Org 1',
updated_at: '2015-02-05 16:37:00', updated_at: '2015-02-05 16:37:00',
@ -73,12 +86,94 @@ class ModelTest < ActiveSupport::TestCase
created_by_id: agent1.id, created_by_id: agent1.id,
) )
references = Models.references('User', agent1.id) # user
# verify agent1
references1 = Models.references('User', agent1.id)
assert_equal(references1['User']['updated_by_id'], 3)
assert_equal(references1['User']['created_by_id'], 1)
assert_equal(references1['Organization']['updated_by_id'], 1)
assert(!references1['Group'])
references_total1 = Models.references_total('User', agent1.id)
assert_equal(references_total1, 7)
# verify agent2
references2 = Models.references('User', agent2.id)
assert(!references2['User'])
assert(!references2['Organization'])
assert(!references2['Group'])
assert(references2.empty?)
references_total2 = Models.references_total('User', agent2.id)
assert_equal(references_total2, 0)
Models.merge('User', agent2.id, agent1.id)
# verify agent1
references1 = Models.references('User', agent1.id)
assert(!references1['User'])
assert(!references1['Organization'])
assert(!references1['Group'])
assert(references1.empty?)
references_total1 = Models.references_total('User', agent1.id)
assert_equal(references_total1, 0)
# verify agent2
references2 = Models.references('User', agent2.id)
assert_equal(references2['User']['updated_by_id'], 3)
assert_equal(references2['User']['created_by_id'], 1)
assert_equal(references2['Organization']['updated_by_id'], 1)
assert(!references2['Group'])
references_total2 = Models.references_total('User', agent2.id)
assert_equal(references_total2, 7)
# org
# verify agent1
references1 = Models.references('Organization', organization1.id)
assert_equal(references1['User']['organization_id'], 1)
assert(!references1['Organization'])
assert(!references1['Group'])
references_total1 = Models.references_total('Organization', organization1.id)
assert_equal(references_total1, 1)
# verify agent2
references2 = Models.references('Organization', organization2.id)
assert(references2.empty?)
references_total2 = Models.references_total('Organization', organization2.id)
assert_equal(references_total2, 0)
Models.merge('Organization', organization2.id, organization1.id)
# verify agent1
references1 = Models.references('Organization', organization1.id)
assert(references1.empty?)
references_total1 = Models.references_total('Organization', organization1.id)
assert_equal(references_total1, 0)
# verify agent2
references2 = Models.references('Organization', organization2.id)
assert_equal(references2['User']['organization_id'], 1)
assert(!references2['Organization'])
assert(!references2['Group'])
references_total2 = Models.references_total('Organization', organization2.id)
assert_equal(references_total2, 1)
assert_equal(references[:model]['User'], 3)
assert_equal(references[:model]['Organization'], 1)
assert_equal(references[:model]['Group'], 0)
assert_equal(references[:total], 6)
end end
end end