Citestore Plugin


I’m currently trying to make a plugin (discourse-citestore) that has the feature of storing data with a handle and a subhandle (locus), so that this data can be automatically accessed by users and pasted in their messages. For example, the plugin would take [us-constitution 1] and replace it with the first paragraph of the Constitution (which would be saved in the database). Here’s the repo:

I’ve gotten some way by simply reading other plugins and trying to adapt what is written in other places into my own needs. But right now I don’t know how to proceed…

As you can see, I have some functions in plugin.rb that deal with the storage creation and data insertion and retrieval. Example:

However, I have no idea on how to access the functions I have set up in that file from the discourse-markdown file citestore.js.es6.

If someone could give me a few pointers, I would appreciate it immensely!

P.s. it may well be that my coding skillz are way too low for the project I have undertaken. I only hope that is not the case…

Add new link on header beside search icon
(James Kiesel) #2

Hi, apologies in advance if I’m dev-splaining anything.

The citestore.js.es6 file is included in the javascript application is sent to your users’ computers when they load up Discourse.

The plugin.rb code lives on the server which is running Discourse.

The way those two things communicate is through API requests. So, for instance, if I load this topic in meta, there’s a request from my computer to the server, requesting information about the topic. You can see what network requests are being made by visiting the ‘Network’ tab in chrome:

(that’s a picture of me requesting the first post in topic 51620. There are many like it, but this one is yours. Note that I’ve filtered out most of the other requests by typing ‘/t/’ into the filter box up top.)

On the client side, you can initiate a request using the ajax library:

import { ajax } from 'discourse/lib/ajax'
getThing() {
  ajax('/citestores/us-constitution-1', function(data) {
    // in here, you can use the data you've fetched!

On the server side, you’ll need to set up a route and a controller to respond with some data when that request is initiated

  Discourse::Application.routes.append do
    get '/citestores/:key', to: 'citesstores#show'
CitestoresController < ApplicationController
  def show
    @citestore = Citestore::Storage.get(params[:key])
    respond_with json: { handle: @citestore.handle, locus: } 

NB: this code is an untested approximation, but should at least get you towards communicating between client and server. :smiley:


Thanks, that’s a great explanation! I think I understood it. Your example had only passing one parameter, :key, how do I pass several?

(James Kiesel) #4


get '/citestores/:param_a/:param_b', to: 'citestores#show'

Alternatively, can also pass whatever params you’d like through the ‘data’ field with ajax:

ajax('/citestores/1.json', { data: { param_b: 'wark' } })

This builds a GET request like this:


which can be picked up in the params on the server side.

params[:param_b] # => 'wark'


Can you clarify something for me, still? I’m looking at the code in discourse-canned-replies and some other places. For example, the following:

return ajax("/posts/" + (this.get('id')) + "/recover", { type: 'PUT', cache: false }).then(function(data){
  .... // Do stuff
}).catch(function(error) {
  .... // Do stuff

So, if I understood correctly, the format is the following, right?

ajax(route, data).then( function(data) { do your stuff } ).catch( function (error) { ... } )

The first message implied that that the format would be something more:

ajax(route, function(data) { do your stuff } );

Or are these the same thing?

Another question: The parameter data that is given after, if it’s JSON, can I use it out of the box? I mean, I have this in plugin.rb:

record = Citestore::Storage.get(user_id, handle, locus)
render json: record

It should be string. So is the data parameter (variable?) a string as well, or do I need to transform it somehow?