Custom auto incrementing fields for string giving duplicate entries
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.
The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.
I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic
def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end
Then the Accounts context has the following code for adding registration number
def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end
put_change(changeset, :registration_number, registration_number)
end
I am betting on the last created student to be having the latest registration number in the above case
Is there a better way of implementing this?
elixir phoenix-framework ecto
add a comment |
I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.
The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.
I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic
def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end
Then the Accounts context has the following code for adding registration number
def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end
put_change(changeset, :registration_number, registration_number)
end
I am betting on the last created student to be having the latest registration number in the above case
Is there a better way of implementing this?
elixir phoenix-framework ecto
add a comment |
I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.
The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.
I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic
def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end
Then the Accounts context has the following code for adding registration number
def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end
put_change(changeset, :registration_number, registration_number)
end
I am betting on the last created student to be having the latest registration number in the above case
Is there a better way of implementing this?
elixir phoenix-framework ecto
I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.
The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.
I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic
def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end
Then the Accounts context has the following code for adding registration number
def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end
put_change(changeset, :registration_number, registration_number)
end
I am betting on the last created student to be having the latest registration number in the above case
Is there a better way of implementing this?
elixir phoenix-framework ecto
elixir phoenix-framework ecto
asked Jan 3 at 16:06
Sigu MagwaSigu Magwa
326314
326314
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You need a bit of synchronized code here :)
Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3
already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state
.
add a comment |
The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.
The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.
Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.
TL;DR: The easiest way to handle this is to let the database handle it.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025893%2fcustom-auto-incrementing-fields-for-string-giving-duplicate-entries%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need a bit of synchronized code here :)
Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3
already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state
.
add a comment |
You need a bit of synchronized code here :)
Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3
already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state
.
add a comment |
You need a bit of synchronized code here :)
Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3
already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state
.
You need a bit of synchronized code here :)
Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3
already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.
defmodule MyApp.RegNumHelper do
@moduledoc false
use GenServer
def start_link(opts),
do: GenServer.start_link(__MODULE__, opts, name: name)
def add_registration_number(changeset),
do: GenServer.call(__MODULE__, {:reg_num, changeset})
@impl true
def init(opts), do: {:ok, opts}
@impl true
def handle_call({:reg_num, changeset}, _from, state) do
# your logic assigning changeset
{:reply, changeset, state}
end
end
This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state
.
answered Jan 4 at 6:31


Aleksei MatiushkinAleksei Matiushkin
84.8k95896
84.8k95896
add a comment |
add a comment |
The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.
The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.
Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.
TL;DR: The easiest way to handle this is to let the database handle it.
add a comment |
The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.
The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.
Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.
TL;DR: The easiest way to handle this is to let the database handle it.
add a comment |
The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.
The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.
Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.
TL;DR: The easiest way to handle this is to let the database handle it.
The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.
The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.
Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.
TL;DR: The easiest way to handle this is to let the database handle it.
edited Jan 3 at 22:46
answered Jan 3 at 22:41
JustAnotherSoulJustAnotherSoul
263313
263313
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025893%2fcustom-auto-incrementing-fields-for-string-giving-duplicate-entries%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown