How to set up the recipient id in public activity
tracked recipient: ->(controller, model) { model && model.user }
assuming Tom is the user of tracked object. Otherwise change model.user
as per your application
Rails Public_Activity gem recipient id getting error
Recipient is looking for a user and not an id. The reason why current_user works is because it is a user object. If you had used current_user.id, it would not have worked.
Use User.find(2) to get the user object.
How to set up friends as recipients in public activity?
I think you would have to do this through custom activity.
For example,
When a new movie is created , you can do the create activity a callback method,
after_create :create_activity
def create_activity
user.friends.each do |friend|
self.create_activity action: :new , parameters: {title:title,poster:poster}, recipient: friend, owner: current_user
end
end
however this solution is very inefficient. I am not sure if there is a method provided for the gem that you can create multiple activities all together, like ActiveRecord, Moview.create([{title:1},{title:2}]). Otherwise you many want to move this into a background job, something like sidekiq .
Multiple recipients of activity
When searching inside the string there's 4 possibilities
- id is in the beginning of the field
ex: "id, 2, 3" - id is in the end of the field
ex: "1, 2, id" - id is in the middle of the field
ex: "1, id, 3" - id is the only number in the field
ex "id"
So here's how i think a query might look like
@activities = PublicActivity::Activity.where(
"user_recipients LIKE ':id,%' or
user_recipients LIKE '%, :id' or
user_recipients LIKE '%, :id,%' or
user_recipients = ':id'", id: current_user.id)
The reason why I can't do a simple LIKE %id%
is that this would match partial numbers, meaning id = 5
will match [1, 10, 15]
though there's no 5
, but 15
does match, so I need to check for the commas ,
to make sure I'm not picking a wrong number.
How to Set [Activity.From.Id] , [member.Id] or [activity.Recipient.Id] using DirectLine?
Regarding my comment, I decided I'd just provide how to do what you want with both packages. Again, if it isn't too much trouble to switch, I highly, highly recommend using Microsoft.Bot.Connector
(newer and more frequently updated) over Microsoft.Bot.Connector.DirectLine
(older, not updated in 2.5 years, and deprecated until/unless we open-source it Update: This isn't actually deprecated, yet. We're currently working on open-sourcing this, but it's a low-priority task).
Recommended: Microsoft.Bot.Connector
Create the conversation with To and From, all-in-one.
var userAccount = new ChannelAccount(toId,toName);
var botAccount = new ChannelAccount(fromId, fromName);
var connector = new ConnectorClient(new Uri(serviceUrl));
IMessageActivity message = Activity.CreateMessageActivity();
if (!string.IsNullOrEmpty(conversationId) && !string.IsNullOrEmpty(channelId))
{
message.ChannelId = channelId;
}
else
{
conversationId = (await connector.Conversations.CreateDirectConversationAsync( botAccount, userAccount)).Id;
}
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId);
message.Text = "Hello, this is a notification";
message.Locale = "en-Us";
await connector.Conversations.SendToConversationAsync((Activity)message);
Credit
Not Recommended: Microsoft.Bot.Connector.DirectLine
This is kind of a hacky workaround, but basically, you create the conversation and then send a ConversationUpdate
activity.
//server side, retrieve token from secret
string directLineSecret = ConfigurationManager.AppSettings["DirectLineSecret"];
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,$"https://directline.botframework.com/v3/directline/tokens/generate");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", directLineSecret);
var fromUser = $"dl_{Guid.NewGuid()}";
request.Content = new StringContent(
JsonConvert.SerializeObject(
new { User = new { Id = fromUser } }),
Encoding.UTF8,
"application/json");
var response = await httpClient.SendAsync(request);
DirectLineToken dlToken = null;
if (response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
dlToken = JsonConvert.DeserializeObject<DirectLineToken>(body);
}
string token = dlToken.token;
//create DirectLineClient from token, client side
DirectLineClient client = new DirectLineClient(token);
var conversation = await client.Conversations.StartConversationAsync();
new System.Threading.Thread(async () => await ReadBotMessagesAsync(client, conversation.ConversationId)).Start();
//send conversationUpdate
var user = new ChannelAccount(fromUser);
await client.Conversations.PostActivityAsync(conversation.ConversationId,
new Activity
{
From = user,
Text = string.Empty,
Type = ActivityTypes.ConversationUpdate,
MembersAdded = new[] { user }
}
);
TimeSpan delayTime = TimeSpan.FromSeconds(dlToken.expires_in) - TimeSpan.FromMinutes(5);
Task.Factory.StartNew(async () =>
{
while (!_getTokenAsyncCancellation.IsCancellationRequested)
{
var t = await client.Tokens.RefreshTokenAsync().ConfigureAwait(false);
await Task.Delay(delayTime, _getTokenAsyncCancellation.Token).ConfigureAwait(false);
}
}).ConfigureAwait(false);
Credit
Using One-to-Many Associations for the Public Activity Rails gem
To save the author you better use the relation while creating the new book
author.books.create(name: "Jaws")
Then if you want to save the reader, you'll need to add it in the args hash
author.books.create(name: "Jaws", reader: some_user)
Note:
The reason why this prefills the object is that when you call new on an active record relation object, all the conditions inside the condition are used to create the new object, for example
Book.where(author: some_author).new
This will generate an instance of book and the author_id
will be the id of the some_author
from the where query.
So when we did an author.books
this created a query
Book.where(author_id: author.id)
And by calling new, the new book will have the id of the author.
PS:
This also works on multiple args in the where
Model.where(key1: value1, key2: value2, key3: value3).new
will create a new instance where the attributes key1
, key2
, key3
are already filled.
Related Topics
How to Install Libksba on MAC Osx
Rails Is Not Using My Global Ruby Version
Argumenterror: Wrong Number of Arguments (1 for 2)
Ruby, How to Access Local Variables Outside the Do - End Loop
Https Request Using Net::Http's Block Form -- Is It Possible
How to Flatten Double Arrays in Mongodb
Why Are My Rspec Tests Failing, But My App Is Working
Ruby 'Range.Last' Does Not Give the Last Value. Why
Could Not Find Gem 'Logstash-Devutils (>= 0) Ruby' in Any of the Gem Sources
Why #!/Usr/Bin/Env Ruby Doesn't Work in Crontab
Rails/Activerecord - Adapternotspecified, Even Though It Is
Using $1, $2, etc. Global Variables Inside Method Definition
Autoload Paths and Nested Services Classes Crash in Ruby
Transliteration with Iconv in Ruby
Require Command Not Working Within Bash Irb on Snow Leopard
Upgrade Ruby on Elastic Beanstalk
How to Assign a Has_Many/Belongs_To Relation Properly in Rails Activerecord