Add site settings for vote limits according to trust levels

Add site settings for vote limits according to trust levels


Add site settings for vote limits according to trust levels


Specifically, it should be possible to upvote more than one answer. The functionality is similar to Reddit or Stack Exchange. The assumption here is that I, as a user, can have preference for more than one answer, and I should be able to vote accordingly.

Use Case

Users on our boards ask questions about technology (containers, MPI) and best practices (infrastructure, job management, etc.). As a user of the board, I commonly like a subset of the answers and would want to move them both up. It’s common to have more than one “good” or “right” answer, but the question not be appropriate for a (non ranked or voted on Discussion Zone). We’re currently not able to do this, and have to choose only one answer.


My time!

Fantastic! I’ll respond in some more detail tomorrow :+1:

@vsoch Ok, I’m going to first lay out some administrative stuff about working with Discourse and contributing to the plugin, then give you some pointers on what you’ll need to do to achieve this. I’m available to asnwer questions on any question, issue or blocker, so don’t hestiate to reach out.

Working with the plugin.

Generally speaking, the Discourse Development Contribution Guidelines apply to working with our plugins. In terms of working with us:

  1. Work on a branch of your fork of the repo.
  2. Commit as you go to make it easier for me to help you out if you get stuck.
  3. When you’re ready, make a PR and I’ll give your work a full review at that stage.

What you’ll need to look at for this task.

Within Discourse the general pattern for limiting user actions is to have seperate limits for each trust level. If you do a search for “tl1” or “tl2” in the config/site_settings.yml you’ll see a number of examples. At a high level, what we’ll be doing here is adding four new site settings:

  • qa_tl1_vote_limit
  • qa_tl2_vote_limit
  • qa_tl3_vote_limit
  • qa_tl4_vote_limit

Adding the settings

Add the settings in the plugin’s config/settings.yml file. They should follow the same format as the other numerical settings in there. Every site setting also needs description text in config/locales/server.en.yml. Copy the format of the other settings for adding that.

Integrating the settings

There are a few places you need to focus on.

  1. The ensure_can_act method in the VotesController. This gets run whenever a create or destroy vote action is sent from the client to the server.

  2. The voted method of the TopicSerializer edit.

  3. The vote method in the qa-post widget on the client.

If you take a look at each of these you’ll see that there is a ‘voted’ property of the topic model that gets determined by the voted class method of Topic on the server. Essentially we need to replace this boolean check with two new properties / methods:

  1. vote_count. A count of how many votes a user has made in a topic; and

  2. can_vote. A comparison of how many votes a user has against the limit for their trust level

There are a number of ways you could do this. Looking at my code now (months / years on) I cringe a little at some of the ways I set this up. However, I think for our purposes now, it’s best if we follow the existing pattern / logic of the plugin, rather than re-think the structure itself.

So that means you’ll need to:

  1. Add two new class methods for vote_count and can_vote to the Topic model on the server. Like the voted method, use a PostCustomField query to count the user’s existing votes.

  2. Update the serializer to serialize these new properties to the client.

  3. Update the checks in the vote method on the client.

Depending on how you go, with 3, you may be able to also improve on it’s current structure. Currently the client voted check is updated optimistically prior to the vote actually getting sent down to the server (one of those things that now makes me cringe).

You could follow that pattern and make a count / limit comparison at this point to determine the can_vote property straight afer the user has voted. However, ideally, you would disable the vote button while the data is being sent down to the server then let the server send back a ‘can_vote’ state which is then used to update the client.

If you want to tackle that structural improvement happy to give you more pointers on how to do things like disable the button while ‘loading’.

That should be enough to start you off, but let me know if you get stuck or need more context / explaination.

1 Like

Hey @angus! I’ve spent upwards of 20 hours on this now, to give you an update I’m totally unable to create a development environment. The links that you provided either have deprecated commands (that don’t work) or ask me to install dependencies on the host. Some of the early issues (that I’ve since worked through) are here External database ENV VARs not documented (external PG Port, external Redis ENV VARs) - installation - Discourse Meta and although the container reports running, I don’t see any active web application. Unless I’m able to have a development environment there is no reasonable way for me to do this.

Hey, sorry to hear you’re struggling! Setting up a Discourse dev env can be frustrating.

Happy to help you work through specific issues. But would also understand if you feel the cost/benefit isn’t worth it.

What env are you using and what issues are you still facing?

hey @angus! Apologies for the delay - I was working on container software and iptables and worried that there was some corruption for Docker (to not see the port 3000) so I wound up purging all of Docker and reinstalling fresh to be absolutely sure. It’s still the case with my docker-compose application that I see no obvious error, but port 3000 isn’t present on the host. I also tried the suggested way:

$ ./bin/docker/boot_dev --init

And again, everything looks okay (from the container logs, docker ps, inspect perspective) but there is nothing shared with the host. I checked all ports being shared:

CONTAINER ID        IMAGE                             COMMAND             CREATED             STATUS              PORTS                                                                                            NAMES
0fd2cea1856c        discourse/discourse_dev:release   "/sbin/boot"        5 minutes ago       Up 5 minutes>1080/tcp,>3000/tcp,>9292/tcp,>9405/tcp   discourse_dev

Across two browsers (chrome and firefox) and each of localhost,, and I’ve also used docker inspect to find the actual address of the container on the bridge, and no go there either. To figure out if this is a docker issue, I’ve tested running other containers that map ports, and I can’t find any issues. So I’m thinking that it has something to do with how discourse is deployed from Docker, possibly specific to my host (Ubuntu 18.04). I’m not sure how to move forward without a development environment, so your help is appreciated!

I don’t know much about the company that can provide discourse, but from this experience it seems like the complexity of the software is their open source business model.

Did you try this Beginners Guide to Install Discourse for Development using Docker - developers - Discourse Meta, it worked for me on Ubuntu 18.04


Hooray I got both of them working! The key was that unicorn command, not all of the getting started guides give instruction to use it. I have to run rake admin:create in the start command, otherwise it wants an email confirmation (full repo here). The discourse_dev works too. Thanks @angus and hopefully I can start actually doing something soon :slight_smile:

And thank you so much @md-misko I wish I had seen your instructions sooner! I had a lot of trouble getting started, but I had a lot of fun earlier with a first go at this PR, so I’m looking forward to more!

Random question for you - do you know of any good source for “work to be done” (akin to good first issues on GitHub boards) that I could peruse and find small things to work on (to help learn ruby?)


The Topics tagged starter-task and bug - Discourse Meta sections should give you lots of opportunities to learn and contribute.


@md-misko Thanks for stepping in here!

@vsoch Let me know if you need any further help on this or other tasks.

You may also find this helpful: