Custom Field not working

Hi All,

I am fairly new to discourse and I am attempting to add a customs field but I am not able to,

Could someone please help me.

My code

after_initialize do

  module ::Foo
  	 PLUGIN_NAME ||= -"discourse-myapi"
     STORE_NAME ||= "replies".freeze

    class Engine < ::Rails::Engine
      engine_name PLUGIN_NAME
      isolate_namespace Foo

    end
  end

  require_dependency "application_controller"


  class Foo::Example
  	class << self

        def bump(id)
           cf_time = Time.zone.now 	
          DistributedMutex.synchronize("#{Foo::PLUGIN_NAME}-#{cf_time.iso8601}") do
          	user = User.find(id)
            user.custom_fields['signature_url'] = cf_time
            user.save!
            return user
          end
        end

  	end	
  end

  class Foo::BarController < ::ApplicationController

  	requires_plugin Foo::PLUGIN_NAME

    def custom_field_test
      begin
        user = Foo::Example.bump(1)
        render json: { user: user }
      rescue StandardError => e
        render_json_error e.message
      end
    end

  end

  Foo::Engine.routes.draw do'
    get  '/custom_field_test' => 'bar#custom_field_test'
  end

  Discourse::Application.routes.append do
    mount ::Foo::Engine, at: '/myapiclass'
  end


end

Thanks

I am going to answer my own question here, since I kind of understand where I was making mistake in terms of my thinking process, and also a benefit of getting feedback from the rest of the team here, as well as for the benefit of new comers to custom_fields functionality in Discourse.

Basically I was making a mistake in thinking without investigation that after I create a custom field on User object by doing

user = User.find(1)
user.custom_fields[“test_field”] = " X X X X"
user.save

I was expecting the custom field to be created on the user object i.e. to become

custome_field_test_field

and I was doing:

user.custom_fields_test_field

But after investigating deeply, I found out that, custom_field is actually an object

user.custom_fields[“test_field”] = { }

and when I do

user.custom_fields[“test_field”] = " X X X X"

it appends it to the hash/object

Therefore it becomes

user.custom_fields = {
"test_field"] = " X X X X"
}

3 Likes

You also want to add a name to your custom field. The importers all use custom fields, so you could look there for examples.

1 Like

Hi @pfaffman

Thanks for feedback, but I am not sure if I am following it, could you please give example.

And also on the rails console if I do

[10] pry(main)&gt; user = **User** .find( **1** )
[11] pry(main)&gt; pp user.custom_fields 

(2.5ms) SELECT "user_custom_fields"."name", "user_custom_fields"."value" FROM "user_custom_fields" WHERE "user_custom_fields"."user_id" = 1 ORDER BY id asc

{"xxxxxxxxxxxxxxxx"=&gt;"2018-06-16 12:23:39 UTC",

 "test_two"=&gt;"1234567",

 "fountain_cake"=&gt;"2018-06-16 13:16:25 UTC"}

=&gt; **{ **"** xxxxxxxxxxxxxxxx **"** =&gt; **"** 2018-06-16 12:23:39 UTC **"** , **"** test_two **"** =&gt; **"** 1234567 **"** , **"** fountain_cake **"** =&gt; **"** 2018-06-16 13:16:25 UTC **"** }**

I can see the custom fields I added,

But on the plugin:

def custom_field_test
  begin
  	 cf_time = Time.zone.now 	
     user = User.find(1)
     user.custom_fields['fountain_cake'] = cf_time
     user.save!
    user_after_update = User.find(1)
    json = serialize_data(user_after_update, UserSerializer, root: false)
    render json: { user: json }
  rescue StandardError => e
    render_json_error e.message
  end
end

It returns the custom_fields as empty object, any thought ?

Look in scripts/import_scripts at any importer to see how they create custom fields.

1 Like

@pfaffman thanks for let me know about the necessary of adding importers for custom field I am looking into them,

On the second part of the question, do you know if Redis caches requests, when you call the DB from rails application ? because at the moment I am two distinct results, calling via the controller and directly to the database via rails console.

Thanks

Anybody know how I can make the “custom_fields” on User visible ? at the moment when I fetch user object I am getting the custom_fields property is empty object/hash - {}.

But if I do user.custom_fields, I can see all the custom fields, however as part of the User object is empty.

Please refer to the code snippet above for more details.

Thanks

For that you have to whitelist those custom fields in either public user custom fields or staff user custom fields site setting according to your need.

3 Likes

@vinothkannans Thanks for reply,

I am new to discourse and I am not sure, when you say - public user custom fields - if you are referring to the UI part of discourse, on JS or the actual Ruby code. could you please elaborate, or point me to an example.

Thanks

I mean you have to add that custom field’s name in admin site setting at the URL /admin/site_settings/category/all_results?filter=public%20user%20custom%20fields like below

@vinothkannansThanks so much,

I can see the field returning as part of the API.

Although I would like to know the wiring under the hood as to why you need to whitelist it ?

Thanks

Custom fields may contain sensitive user data. We shouldn’t expose it by default.

3 Likes

is this features work for requirement, I want to see all users in two different categories, “supplier” or “customer”

If i add into customize → User Fields → Filed Type → Dropdown > Add Field Name

Require tick from below two
Options
Supplier
Customer

Can anyone help me for that, Where i can see this report? It is come with > users List

You probably need the data Explorer plugin to get a report.

1 Like

@vinothkannans . Thanks for replying.

And I have another question about custom fields, I am not able to see the custom_field on Posts object, nor I can whitelist it on the ui admin page, can you help with this,

Thanks

You should manually add it from a plugin using add_to_serializer(:post, ... method.

5 Likes

@vinothkannans Thanks for suggestion, and it’s working.

One more thing I would like to ask you is, I am trying to set an object as in a JSON object into the custom field, However, when I se it, is setting it as a string with character escapes, is there a way to handle this.

Thanks

JSON.parse(post.custom_fields["FIELD_NAME"])

You can use above command to convert the string to JSON object.

2 Likes

Thanks @vinothkannans

Last question, do you know if is possible in Discourse, to intercept a response from POST request, modify the body, e.g. add a custom field before sending to the client ?

Thanks

Yes, it’s possible. You should go through to the available methods in plugin/instance.rb file. You can also check existing plugin codes to learn about how they handling different situations. And go through Beginner's Guide to Creating Discourse Plugins Part 1: Creating a basic plugin.

Edit: You can also monkey patch controller methods.

3 Likes