Skip to content

Feedback wanted: scored elections#387

Open
reentim wants to merge 6 commits intorubyaustralia:mainfrom
reentim:election-voting
Open

Feedback wanted: scored elections#387
reentim wants to merge 6 commits intorubyaustralia:mainfrom
reentim:election-voting

Conversation

@reentim
Copy link
Contributor

@reentim reentim commented Oct 9, 2025

This is an incomplete sketch of a how we could model scored elections, per #379.

It seems like there's a lack of consensus as to what form scored voting should take and whether it's something we should build ourselves. And assuming we did build it, there's many ways to go about it.

This approach is informed by the discussion in the issue, and the relevant parts of the constitution (below).

If we do want to proceed along these lines, I can flesh out the validations and build a front end. For now I'd suggest that nominations be collected following the current process and entered using a simple form, and users nominating / consenting to nominations could happen in-app as a later enhancement.

50 Nominations

  1. Prior to the election of each position, the Chairperson of the meeting must call for nominations to fill that position. Nominations may be voiced by completing the nomination form and returning it before the meeting.

  2. An eligible member of the Association may—

    1. nominate themself; or
    2. with the member's consent, be nominated by another member.
  3. A member who is nominated for a position and fails to be elected to that position may be nominated for any other position for which an election is yet to be held.

  4. Nominations are held twice a year at the AGM and an SGM for each position that expires at that time.

51 Election of President etc.

  1. At the annual general meeting and SGM where nominations occur separate elections must be held for each of the following positions—

    1. President;
    2. Vice-President;
    3. Secretary;
    4. Treasurer.
  2. If only one member is nominated for the position, the Chairperson of the meeting must declare the member elected to the position.

  3. If more than one member is nominated, a ballot must be held.

52 Election of ordinary members

  1. The annual general meeting may by resolution decide the number of ordinary members of the Committee (if any) it wishes to hold office for the next year.

  2. A single election may be held to fill all of those positions in so far as the position is vacant at that meeting.

  3. If the number of members nominated for the position of ordinary committee member is less than or equal to the number to be elected, the Chairperson of the meeting must declare each of those members to be elected to the position.

  4. If the number of members nominated exceeds the number to be elected, a ballot must be held.

Copy link
Member

@quintrino quintrino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's looking really well thought out over all.

I'm not sure if you want to address my changes immediately or leave it for a v2.

Let me know.


has_many :nominations
has_many :votes, through: :nominations
has_many :nominated_candidates, through: :nominations, source: :nominee
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nominated_candidates somewhat rules out if the vote is on something other than an election (ie, if it was about voting on the approval of a new constitutional change )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was seeing Election as being specifically about committee member election. Since there are different rules around resolutions and special resolutions, it probably makes sense to have separate models. Instead of belonging to nominations, votes would belong to a polymorphic votable — nominations, resolutions, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it's not always going to be a resolution either, ideally it could theoretically be voting on a new mascot or something.


private

def top_scoring_candidates
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So would we have multiple elections/votes for each role?

So I can imagine a separate vote for President, and then a vote for Secretary, but let's assume that we have a general members election and Candidate A is keen to run for both Sponsor Outreach and Diversity Lead, my first thought is to the option to vote for
Candidate A - Sponsor Outreach
Candidate A - Diversity National Lead
and then if they were the highest voted option for both then they would choose which role they wanted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention with this method returning multiple users is to accommodate both elections for President etc., and the election of ordinary members.

President etc

  • election vacancies set to 1, and so top_scoring_candidates returns one user.
  • one election per position per year / term of office

Ordinary members

  • AGM decides by resolution number of ordinary members to hold office, sets election vacancies accordingly
  • single election held to fill all vacancies
  • top_scoring_candidates returns number of users required to fill vacancies.

Your scenario is interesting, and possibly I've either misinterpreted the process for ordinary members, or, in "A single election may be held", the word "may" is key. Is it typical to hold an election (ballot) per office to be held by an ordinary member?

In any case, I reckon this scenario of a candidate running for multiple positions could be handled by the candidate withdrawing acceptance for the nomination, and scoping accordingly here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I'm understanding this correctly if we had 4 open ordinary members this would returns the 4 nominations with the most votes? Would that be in order?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, there would be 4 vacancies, so this query would get the 4 top scoring nominations (so not necessarily the nominations with the most votes -- e.g. a nomination with 1 vote with a score of 10 beats a nomination with 9 votes with a score of 1).

It then returns the users referenced by the nominations, in no particular order.

And this code path is only invoked if there are more nominations than vacancies (i.e. voting is required).

t.index ["user_id"], name: "index_memberships_on_user_id"
end

create_table "nominations", force: :cascade do |t|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do want us to be able to support votes on things other than Users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think votes would have a polymorphic association in that case (see my other comment).

# created_at :datetime not null
# updated_at :datetime not null
#
class Election < ApplicationRecord
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the Election should have a title of what is being voted on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

position :string was intended for that, maybe the naming could be improved.

@reentim reentim force-pushed the election-voting branch 4 times, most recently from fe9ec7f to 6c055b6 Compare November 27, 2025 07:10
@reentim
Copy link
Contributor Author

reentim commented Jan 7, 2026

Hey team, pushing up what I've got so far, with some failing tests, and visual inconsistencies, as @quintrino is keen to get progress. Help would be appreciated from someone who has more knowledge of Tailwind and the preferred visual language of Ruby Australia than me, as there's a bunch of seemingly inconsistent styles, headings, etc. available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement frontend help wanted ruby Pull requests that update Ruby code task

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants