Introduced create_if_not_exists_with_ref and create_or_update_with_ref for automatically lookup references by name/login.

This commit is contained in:
Martin Edenhofer 2016-06-18 16:54:26 +02:00
parent b348d70f23
commit 5d13730515
5 changed files with 490 additions and 47 deletions

View file

@ -288,12 +288,30 @@ returns
do name/login/email based lookup for associations do name/login/email based lookup for associations
params = {
login: 'some login',
firstname: 'some firstname',
lastname: 'some lastname',
email: 'some email',
organization: 'some organization',
roles: ['Agent', 'Admin'],
}
attributes = Model.param_association_lookup(params) attributes = Model.param_association_lookup(params)
returns returns
attributes = params # params with possible lookups attributes = params # params with possible lookups
attributes = {
login: 'some login',
firstname: 'some firstname',
lastname: 'some lastname',
email: 'some email',
organization_id: 123,
role_ids: [2,1],
}
=end =end
def self.param_association_lookup(params) def self.param_association_lookup(params)
@ -309,33 +327,84 @@ returns
value = data[assoc.name.to_sym] value = data[assoc.name.to_sym]
next if !value # next if we do not have a value next if !value # next if we do not have a value
ref_name = "#{assoc.name}_id" ref_name = "#{assoc.name}_id"
next if !available_attributes.include?(ref_name) # next if we do not have an _id attribute
next if data[ref_name.to_sym] # next if we have already the id filled # handle _id values
if available_attributes.include?(ref_name) # if we do have an _id attribute
next if data[ref_name.to_sym] # next if we have already the _id filled
# get association class and do lookup
class_object = assoc.klass
lookup = nil
if class_object == User
if value.class == String
if !lookup
lookup = class_object.lookup(login: value)
end
if !lookup
lookup = class_object.lookup(email: value)
end
else
raise "String is needed as ref value #{value.inspect} for '#{assoc.name}'"
end
else
lookup = class_object.lookup(name: value)
end
# complain if we found no reference
if !lookup
raise "No lookup value found for '#{assoc.name}': #{value.inspect}"
end
# release data value
data.delete(assoc.name.to_sym)
# remember id reference
data[ref_name.to_sym] = lookup.id
next
end
next if value.class != Array
next if value.empty?
next if value[0].class != String
# handle _ids values
ref_names = "#{assoc.name[0, assoc.name.length - 1]}_ids"
generic_object_tmp = new
next unless generic_object_tmp.respond_to?(ref_names) # if we do have an _ids attribute
next if data[ref_names.to_sym] # next if we have already the _ids filled
# get association class and do lookup # get association class and do lookup
class_object = assoc.klass class_object = assoc.klass
lookup = nil lookup_ids = []
if class_object == User value.each {|item|
if !lookup lookup = nil
lookup = class_object.lookup(login: value) if class_object == User
if item.class == String
if !lookup
lookup = class_object.lookup(login: item)
end
if !lookup
lookup = class_object.lookup(email: item)
end
else
raise "String is needed in array ref as ref value #{value.inspect} for '#{assoc.name}'"
end
else
lookup = class_object.lookup(name: item)
end end
if !lookup
lookup = class_object.lookup(email: value)
end
else
lookup = class_object.lookup(name: value)
end
# complain if we found no reference # complain if we found no reference
if !lookup if !lookup
raise "No lookup value found for '#{assoc.name}': #{value.inspect}" raise "No lookup value found for '#{assoc.name}': #{item.inspect}"
end end
lookup_ids.push lookup.id
}
# release data value # release data value
data.delete(assoc.name.to_sym) data.delete(assoc.name.to_sym)
# remember id reference # remember id reference
data[ref_name.to_sym] = lookup.id data[ref_names.to_sym] = lookup_ids
} }
data data
@ -613,6 +682,23 @@ returns
=begin =begin
Model.create_if_not_exists with ref lookups
result = Model.create_if_not_exists_with_ref(attributes)
returns
result = model # with all attributes
=end
def self.create_if_not_exists_with_ref(data)
data = param_association_lookup(data)
create_or_update(data)
end
=begin
create or update model (check exists based on id, name, login, email or locale) create or update model (check exists based on id, name, login, email or locale)
result = Model.create_or_update(attributes) result = Model.create_or_update(attributes)
@ -708,6 +794,23 @@ returns
=begin =begin
Model.create_or_update with ref lookups
result = Model.create_or_update(attributes)
returns
result = model # with all attributes
=end
def self.create_or_update_with_ref(data)
data = param_association_lookup(data)
create_or_update(data)
end
=begin
activate latest change on create, update, touch and destroy activate latest change on create, update, touch and destroy
class Model < ApplicationModel class Model < ApplicationModel

View file

@ -12,7 +12,14 @@
"firstname": "Agent 1", "firstname": "Agent 1",
"lastname": "Test", "lastname": "Test",
"email": "agent1@example.com", "email": "agent1@example.com",
"password": "test" "password": "test",
"roles": ["Agent"]
}
],
"Groups": [
{
"name": "some group1",
"users": ["master@example.com","agent1@example.com"]
} }
], ],
"Settings": [ "Settings": [

View file

@ -33,7 +33,7 @@ returns
def self.data def self.data
auto_wizard_file_location = file_location auto_wizard_file_location = file_location
raise "So such file #{auto_wizard_file_location}" if !File.file?(auto_wizard_file_location) raise "So such file #{auto_wizard_file_location}" if !File.file?(auto_wizard_file_location)
JSON.parse( File.read(auto_wizard_file_location) ) JSON.parse(File.read(auto_wizard_file_location))
end end
=begin =begin
@ -77,38 +77,34 @@ returns
} }
end end
# create Organizations # create EmailAddresses/Channels/Signatures
if auto_wizard_hash['Organizations'] model_map = {
auto_wizard_hash['Organizations'].each { |organization_data| 'Organizations' => 'Organization',
Organization.create_or_update(organization_data.symbolize_keys) }
model_map.each {|map_name, model|
next if !auto_wizard_hash[map_name]
auto_wizard_hash[map_name].each {|data|
generic_object = Kernel.const_get(model)
data.symbolize_keys!
generic_object.create_or_update_with_ref(data)
} }
end }
# create Users # create Users
if auto_wizard_hash['Users'] if auto_wizard_hash['Users']
roles = Role.where( name: %w(Agent Admin) )
groups = Group.all
auto_wizard_hash['Users'].each { |user_data| auto_wizard_hash['Users'].each { |user_data|
user_data.symbolize_keys!
# lookup organization if admin_user.id == 1
if user_data['organization'] && !user_data['organization'].empty? if !user_data[:roles] && !user_data[:role_ids]
organization = Organization.find_by(name: user_data['organization']) user_data[:roles] = Role.where(name: %w(Agent Admin))
if organization end
user_data['organization_id'] = organization.id if !user_data[:groups] && !user_data[:group_ids]
user_data[:groups] = Group.all
end end
end end
user_data.delete('organization')
user_data_symbolized = user_data.symbolize_keys.merge( created_user = User.create_or_update_with_ref(user_data)
{
active: true,
roles: roles,
groups: groups,
}
)
created_user = User.create_or_update(user_data_symbolized)
# use first created user as admin # use first created user as admin
next if admin_user.id != 1 next if admin_user.id != 1
@ -133,11 +129,9 @@ returns
model_map.each {|map_name, model| model_map.each {|map_name, model|
next if !auto_wizard_hash[map_name] next if !auto_wizard_hash[map_name]
auto_wizard_hash[map_name].each {|data| auto_wizard_hash[map_name].each {|data|
if data['id'] || data['name'] generic_object = Kernel.const_get(model)
Kernel.const_get(model).create_or_update(data.symbolize_keys) data.symbolize_keys!
else generic_object.create_or_update_with_ref(data)
Kernel.const_get(model).create(data.symbolize_keys)
end
} }
} }

View file

@ -0,0 +1,170 @@
# encoding: utf-8
require 'test_helper'
class AutoWizardTest < ActiveSupport::TestCase
test 'simple' do
auto_wizard_data = {
Users: [
{
login: 'master_unit_test01@example.com',
firstname: 'Test Master',
lastname: 'Agent',
email: 'master_unit_test01@example.com',
password: 'test',
},
{
login: 'agent1_unit_test01@example.com',
firstname: 'Agent 1',
lastname: 'Test',
email: 'agent1_unit_test01@example.com',
password: 'test',
roles: ['Agent'],
}
],
Groups: [
{
name: 'some group1',
users: ['master_unit_test01@example.com', 'agent1_unit_test01@example.com']
}
],
Settings: [
{
name: 'developer_mode',
value: true
},
{
name: 'product_name',
value: 'Zammad UnitTest01 System'
},
]
}
assert_equal(false, AutoWizard.enabled?)
auto_wizard_file_write(auto_wizard_data)
assert_equal(true, AutoWizard.enabled?)
AutoWizard.setup
assert_equal(false, AutoWizard.enabled?)
# check first user roles
auto_wizard_data[:Users][0][:roles] = %w(Agent Admin)
auto_wizard_data[:Users].each {|local_user|
user = User.find_by(login: local_user[:login])
assert_equal(local_user[:login], user.login)
assert_equal(local_user[:firstname], user.firstname)
assert_equal(local_user[:lastname], user.lastname)
assert_equal(local_user[:email], user.email)
assert_equal(local_user[:roles].count, user.role_ids.count)
next unless local_user[:roles]
local_user[:roles].each {|local_role_name|
local_role = Role.find_by(name: local_role_name)
assert(user.role_ids.include?(local_role.id))
}
}
auto_wizard_data[:Groups].each {|local_group|
group = Group.find_by(name: local_group[:name])
assert_equal(local_group[:name], group.name)
next unless local_group[:users]
local_group[:users].each {|local_user_login|
local_user = User.find_by(login: local_user_login)
assert(group.user_ids.include?(local_user.id))
}
}
auto_wizard_data[:Settings].each {|local_setting|
setting_value = Setting.get(local_setting[:name])
assert_equal(local_setting[:value], setting_value)
}
end
test 'complex' do
auto_wizard_data = {
Organizations: [
{
name: 'Auto Wizard Test Org',
shared: false,
}
],
Users: [
{
login: 'master_unit_test01@example.com',
firstname: 'Test Master',
lastname: 'Agent',
email: 'master_unit_test01@example.com',
password: 'test',
organization: 'Auto Wizard Test Org',
roles: ['Admin'],
},
{
login: 'agent1_unit_test01@example.com',
firstname: 'Agent 1',
lastname: 'Test',
email: 'agent1_unit_test01@example.com',
password: 'test',
roles: ['Agent'],
}
],
Groups: [
{
name: 'some group1',
users: ['master_unit_test01@example.com', 'agent1_unit_test01@example.com']
}
],
Settings: [
{
name: 'developer_mode',
value: false,
},
{
name: 'product_name',
value: 'Zammad UnitTest02 System'
},
]
}
assert_equal(false, AutoWizard.enabled?)
auto_wizard_file_write(auto_wizard_data)
assert_equal(true, AutoWizard.enabled?)
AutoWizard.setup
assert_equal(false, AutoWizard.enabled?)
auto_wizard_data[:Users].each {|local_user|
user = User.find_by(login: local_user[:login])
assert_equal(local_user[:login], user.login)
assert_equal(local_user[:firstname], user.firstname)
assert_equal(local_user[:lastname], user.lastname)
assert_equal(local_user[:email], user.email)
next unless local_user[:roles]
assert_equal(local_user[:roles].count, user.role_ids.count)
local_user[:roles].each {|local_role_name|
local_role = Role.find_by(name: local_role_name)
assert(user.role_ids.include?(local_role.id))
}
}
auto_wizard_data[:Groups].each {|local_group|
group = Group.find_by(name: local_group[:name])
assert_equal(local_group[:name], group.name)
next unless local_group[:users]
local_group[:users].each {|local_user_login|
local_user = User.find_by(login: local_user_login)
assert(group.user_ids.include?(local_user.id))
}
}
auto_wizard_data[:Settings].each {|local_setting|
setting_value = Setting.get(local_setting[:name])
assert_equal(local_setting[:value], setting_value)
}
end
def auto_wizard_file_write(data)
location = "#{Rails.root}/auto_wizard.json"
file = File.new(location, 'wb')
file.write(data.to_json)
file.close
end
def auto_wizard_file_exists?
location = "#{Rails.root}/auto_wizard.json"
return false if File.exist?(location)
true
end
end

View file

@ -0,0 +1,169 @@
# encoding: utf-8
require 'test_helper'
class ObjectCreateUpdateWithRefNameTest < ActiveSupport::TestCase
test 'organization' do
roles = Role.where(name: %w(Agent Admin))
groups = Group.all
user1 = User.create_or_update(
login: 'object_ref_name1@example.org',
firstname: 'object_ref_name1',
lastname: 'object_ref_name1',
email: 'object_ref_name1@example.org',
password: 'some_pass',
active: true,
updated_by_id: 1,
created_by_id: 1,
roles: roles,
groups: groups,
)
user2 = User.create_or_update(
login: 'object_ref_name2@example.org',
firstname: 'object_ref_name2',
lastname: 'object_ref_name2',
email: 'object_ref_name2@example.org',
password: 'some_pass',
active: true,
updated_by_id: 1,
created_by_id: 1,
roles: roles,
groups: groups,
)
org1 = Organization.create_if_not_exists_with_ref(
name: 'some org update_with_ref member',
members: ['object_ref_name1@example.org'],
updated_by_id: 1,
created_by_id: 1,
)
assert(org1.member_ids.sort.include?(user1.id))
assert_not(org1.member_ids.sort.include?(user2.id))
org2 = Organization.create_or_update_with_ref(
name: 'some org update_with_ref member',
members: ['object_ref_name2@example.org'],
updated_by_id: 1,
created_by_id: 1,
)
assert_not(org2.member_ids.sort.include?(user1.id))
assert(org2.member_ids.sort.include?(user2.id))
assert_equal(org1.id, org2.id)
org3 = Organization.create_or_update_with_ref(
name: 'some org update_with_ref member2',
members: ['object_ref_name2@example.org'],
updated_by_id: 1,
created_by_id: 1,
)
assert_not(org3.member_ids.sort.include?(user1.id))
assert(org3.member_ids.sort.include?(user2.id))
assert_not_equal(org2.id, org3.id)
assert_raises( ActiveRecord::AssociationTypeMismatch ) {
Organization.create_or_update_with_ref(
name: 'some org update_with_ref member2',
members: ['object_ref_name2@example.org'],
member_ids: [2],
updated_by_id: 1,
created_by_id: 1,
)
}
end
test 'user' do
org1 = Organization.create_if_not_exists_with_ref(
name: 'some org update_with_ref user',
updated_by_id: 1,
created_by_id: 1,
)
user1 = User.create_or_update_with_ref(
login: 'object_ref_name1@example.org',
firstname: 'object_ref_name1',
lastname: 'object_ref_name1',
email: 'object_ref_name1@example.org',
password: 'some_pass',
active: true,
organization: 'some org update_with_ref user',
updated_by_id: 1,
created_by_id: 1,
roles: %w(Agent Admin),
groups: ['Users'],
)
user2 = User.create_or_update_with_ref(
login: 'object_ref_name2@example.org',
firstname: 'object_ref_name2',
lastname: 'object_ref_name2',
email: 'object_ref_name2@example.org',
password: 'some_pass',
organization_id: nil,
active: true,
updated_by_id: 1,
created_by_id: 1,
roles: ['Customer'],
groups: [],
)
admin_role = Role.lookup(name: 'Admin')
agent_role = Role.lookup(name: 'Agent')
customer_role = Role.lookup(name: 'Customer')
users_group = Group.lookup(name: 'Users')
assert(user1.organization.name, 'some org update_with_ref user')
assert(user1.group_ids.include?(users_group.id))
assert(user1.role_ids.include?(admin_role.id))
assert(user1.role_ids.include?(agent_role.id))
assert_not(user1.role_ids.include?(customer_role.id))
assert_equal(nil, user2.organization_id)
assert_not(user2.group_ids.include?(users_group.id))
assert_not(user2.role_ids.include?(admin_role.id))
assert_not(user2.role_ids.include?(agent_role.id))
assert(user2.role_ids.include?(customer_role.id))
end
test 'group' do
user1 = User.create_or_update_with_ref(
login: 'object_ref_name1@example.org',
firstname: 'object_ref_name1',
lastname: 'object_ref_name1',
email: 'object_ref_name1@example.org',
password: 'some_pass',
active: true,
organization_id: nil,
updated_by_id: 1,
created_by_id: 1,
roles: %w(Agent Admin),
groups: [],
)
user2 = User.create_or_update_with_ref(
login: 'object_ref_name2@example.org',
firstname: 'object_ref_name2',
lastname: 'object_ref_name2',
email: 'object_ref_name2@example.org',
password: 'some_pass',
organization_id: nil,
active: true,
updated_by_id: 1,
created_by_id: 1,
roles: ['Customer'],
groups: [],
)
group1 = Group.create_if_not_exists_with_ref(
name: 'some group update_with_ref',
users: ['object_ref_name1@example.org'],
updated_by_id: 1,
created_by_id: 1,
)
assert(group1.name, 'some group update_with_ref')
assert(group1.user_ids.include?(user1.id))
assert_not(group1.user_ids.include?(user2.id))
end
end