# Adding a ruby controller via plugin

**URL:** <https://meta.discourse.org/t/adding-a-ruby-controller-via-plugin/60661>\
**Category:** Development\
**Created:** [2017 年4 月 8 日 20:28 UTC](https://meta.discourse.org/t/adding-a-ruby-controller-via-plugin/60661 "2017-04-08T20:28:11Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

作者： ![jomaxro](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jomaxro/32/126216_2.png) [@jomaxro](https://meta.discourse.org/u/jomaxro)\
发布日期： [2017 年4 月 8 日 20:28 UTC](https://meta.discourse.org/t/adding-a-ruby-controller-via-plugin/60661/1 "2017-04-08T20:28:11Z")

</div>

_Please bare with me here - first time developing a Discourse plugin. Was thrown into this project by my job…_

**Background:**  
This is a continuation of [this post](https://meta.discourse.org/t/change-last-read-post-number-for-user-via-api/60454). For clarity, I’ll repeat the background here.

My company runs an internal Discourse Forum, as well as an internal WordPress site. The forums are configured to use SSO from the WordPress instance. On the forums, there is a category called “Updates”. On the WordPress side, when a user logs in there is the following PHP function:

```plaintext
$results = $this->_getRequest("c/updates.json", null, $username);

```

The `$results` are then parsed. For each topic, if the `last_read_post_number < highest_post_number` then we assume the user hasn’t fully read the topic and display an excerpt of the topic in a div on the WordPress site. In the div, there is an `X`. The intention is that clicking the `X` will set the user’s `last_read_post_number` equal to the `highest_post_number` so it is “read” in the forums too.

This was initially set up over a year ago by adding a custom controller and route to make the `last_read_post_number`. Problem is the route was set in a way that overwrote the Discourse `routes.rb` file, causing intermittent and eventually permanent problems. In the old topic I asked if there was a way to do this via the API, so I could integrate the code into WordPress. After chatting with engineering, it was determined that the PHP/JS code for the alerts were written by a previous contractor and were not going to be touched as they currently work.

As such, I’m now looking to recreate the old setup “properly”, which I’m assuming means a plugin. The old setup added two files via `app.yml`

```plaintext
run:
  - exec: echo "Beginning of custom commands"
  - replace:
      filename: "/etc/nginx/conf.d/discourse.conf"
      from: /client_max_body_size.+$/
      to: client_max_body_size 512m;
  - exec: cp /shared/routes.rb /var/www/discourse/config/routes.rb
  - exec: cp /shared/staff_corner_controller.rb /var/www/discourse/app/controllers/staff_corner_controller.rb

```

**`/shared/routes.rb`**  
A 1±year-old copy of the Discourse `routes.rb` file with `get "staffcorner/mark-read/:pulseUserId/:topicId" => "staffcorner#mark_read"` added to the `Discourse::Application.routes.draw do` section.

**`/shared/staff_corner_controller.rb`**

```plaintext
class StaffcornerController < ApplicationController
        skip_before_filter :check_xhr, :redirect_to_login_if_required
        skip_before_filter :require_login
    def mark_read
        pulseUserId = params[:pulseUserId]
        topicId = params[:topicId]
        sso_record = SingleSignOnRecord.where(external_id: pulseUserId).first
        #wsUrl = SiteSetting.pulse_ws_url
        # No record yet, so create it
        if (!sso_record)
            # Load Pulse roles
            res = Net::HTTP.post_form(URI('http://webservices.idtech.com/StaffCorner.asmx/GetUserInfoByUserID'), {'Authenticate' => '{REDACTED}', 'companyID' => '1', 'userID' => pulseUserId})
            data = XmlSimple.xml_in(res.body)
            userData = data['diffgram'][0]['Result'][0]['User'][0]
            email = userData['Email'][0]
            username = email
            name = userData['FirstName'][0]
            user = User.where(:email => email).first
        end
        user = user || sso_record.user
        topic = Topic.find(topicId)
        if (!topic)
                render :json => {success: false, message: "Unknown topic"}
                return
        end
        topicUser = TopicUser.where(:user_id => user.id, :topic_id => topic.id).first
        if (!topicUser)
                topicUser = TopicUser.create(:user => user, :topic => topic, :last_read_post_number => topic.posts.last)
        end
        topicUser.last_read_post_number = topic.posts.last.id
        topicUser.save
        render :json => {success: true}
    end
end

```

* * *

I’ve tried implementing this as a plugin, but I’m not suceeding… Here’s what I’ve got at the moment.

**Structure:**

```plaintext
/staff-forum-plugin
..plugin.rb
../app
..../controllers
....../staff_corner_controller.rb
../config
....settings.yml
..../locales
......server.en.yml

```

**plugin.rb:**

```plaintext
# name: staff-forum-plugin
# about: Adds a route for staff corner to mark topics as read
# version: 0.1.0
# authors: Joshua Rosenfeld
# url: {Internal}
enabled_site_setting :mark_read_enabled
after_initialize do
    module ::StaffForumsMarkRead
        class Engine < ::Rails::Engine
            engine_name "staff_forums_mark_read"
            isolate_namespace StaffForumsMarkRead
        end
    end
    
    require_dependency 'application_controller'
    class StaffForumsMarkRead::MarkReadController < ::ApplicationController
        before_action :ensure_plugin_enabled
        def ensure_plugin_enabled
            raise Discourse::InvalidAccess.new('Staff Forums Mark Read plugin is not enabled') if !SiteSetting.mark_read_enabled
        end
    end
    
    Discourse::Application.routes.append do
        get "staffcorner/mark-read/:pulseUserId/:topicId" => "staffcorner#mark_read"
    end
end

```

**staff\_corner\_controller.rb:**  
Same as above

**settings.yml:**

```plaintext
plugins:
  mark_read_enabled:
    default: true
    client: true

```

**server.en.yml:**

```plaintext
en:
    site_settings:
        mark_read_enabled: "Allow Staff Corner important updates banner to mark topics as read?"

```

* * *

Any thoughts, ideas, etc. would be much appreciated. This worked (at least it accomplished what it was supposed to do) when the files were copied as part the `app.yml` custom commands - but doing this broke the site, so I just need to figure out how to add the files the correct way.

---

_[View the full topic](https://meta.discourse.org/t/adding-a-ruby-controller-via-plugin/60661)._
