How to query the Noticed gem json field - ruby-on-rails

I am using Noticed gem for my notifications and I am trying to query for the notifications related to the post.
The notification stores the post as an object inside params.
#<Notification id: 10, params: {:post=>#<Post id: 3}>
I can target like
notification.params[:post][:id]
=> 3
What I am trying to accomplish is something like this:
Notifications.where(params[:post][:id] => 3)
Is there a way to do that or my approach should be different?
Edited:
Here is an example of a notification in the database:
#<Notification id: 10, recipient_type: "User", recipient_id: 8, type: "MessageNotification", params: {:user=>#<User id: 3, email: "test2#test2.com", created_at: "2021-01-06 23:34:46", updated_at: "2021-04-15 17:47:54", admin: true>, :conversation=>#<Mailboxer::Conversation id: 6, subject: "Hello", created_at: "2021-05-14 00:14:41", updated_at: "2021-05-14 00:26:06">}, read_at: nil, created_at: "2021-05-14 00:26:06", updated_at: "2021-05-14 17:11:50">
squema.rb
t.jsonb "params"
A query suggested by #Joel_Blum and the slq call:
>> current_user.notifications.where('params #> ?', {conversation: {id: 6}}.to_json).to_sql
=> "SELECT \"notifications\".* FROM \"notifications\" WHERE \"notifications\".\"recipient_id\" = 8 AND \"notifications\".\"recipient_type\" = 'User' AND (params #> '{\"conversation\":{\"id\":6}}')"
Returns => #<ActiveRecord::AssociationRelation []>

It seems the gem creates either a jsonb or json column depending on your db.
So what want is perform a search on a json(b) column
For postgres for example it can be done like this
Notification.where('params #> ?', {post: {id: 3}}.to_json)

For whatever reason I am getting an empty array on a notification that I am sure exists.
query: Notification.where('params #> ?', {comment: {id: testc.id}}.to_ json)
SQL: "SELECT \"notifications\".* FROM \"notifications\" WHERE (params #> '{\"comment\":{\"id\":656}}')"

Noticed has a built in way of querying for objects you send in the params.
If you add has_noticed_notifications to the Post model, you should then be able to call #post.notifications_as_post
This is in the Noticed readme here. I definitely came here and found this question before I found the details in the readme!

Related

Rails Query based on hasManyBelongsToMany relation

I have the following models
venues(id, name, ....)
categories(id, name, ....)
categories_venues(id, venue_id, category_id)
I want to query venues based which have the relation of Categories ID = (1)/(2) or (1 and 2)
How can i do a where query for the relation of a HABTM?
EDIT
Using the following query it solved the problem.
venues = Venue.joins(:categories_venues).where(:categories_venues => {:category_id => values})
I want to exclude repetitive records from the query and a particular ID from the results?
---
- !ruby/object:Venue
attributes:
id: 2
name: Ooty
slug: ooty
created_at: 2014-06-21 22:10:52.000000000 Z
updated_at: 2014-07-05 17:33:26.000000000 Z
- !ruby/object:Venue
attributes:
id: 4
name: Munnar
slug: munnar
created_at: 2014-08-25 03:42:13.000000000 Z
updated_at: 2014-08-25 03:42:13.000000000 Z
- !ruby/object:Venue
attributes:
id: 2
name: Ooty
slug: ooty
created_at: 2014-06-21 22:10:52.000000000 Z
updated_at: 2014-07-05 17:33:26.000000000 Z
Not sure if understanding you right. Plz provide sql code if you think this answer does not provide the right query
But i think, it should be just
Venue.joins(:categories).where(category_id: [1,2])
You can use below query to get venue details based on category
venues = Venue.joins(:categories_venues).where(:categories_venues => {:category_id => values})

Why do I keep getting WhereChain Query due to scope?

So i'm trying to create a scope that takes two variables, (current_user, other_user) and seperate the messages between the two based off of sender_id and receiver_id (my foreign_keys).
I've used the following before on a project, and it worked well:
scope :between, -> (me, other) { Message.where{((:sender_id == my{me.id}) & (:receiver_id == my{other.id})) | ((:sender_id == my{other.id}) & (:receiver_id == my{me.id}))}}
However, on my current project, I use the same thing, and it's doing two things.
1: After binding.pry it provides this response.
[1] pry(#<ConversationsController>)> #messages
Message Load (0.4ms) SELECT "messages".* FROM "messages"
=> #<ActiveRecord::QueryMethods::WhereChain:0x00000106d83c98
#scope=
[#<Message id: 1, title: nil, body: "Message 1", sender_id: 11, receiver_id: 1, created_at: "2014-05-20 19:29:34", updated_at: "2014-05-20 19:29:34">,
#<Message id: 2, title: nil, body: "Message 2", sender_id: 1, receiver_id: 11, created_at: "2014-05-20 19:30:15", updated_at: "2014-05-20 19:30:15">,
#<Message id: 3, title: nil, body: "radda?", sender_id: 1, receiver_id: 109, created_at: "2014-05-20 19:30:39", updated_at: "2014-05-20 19:30:39">]>
As you can see above, it's combining all user id's, not just the sender and receiver. So all users receive all messages. And then, I keep getting this WhereChain Error.
#<ActiveRecord::QueryMethods::WhereChain:0x00000107f99ea0>
Please help me understand what I may be doing wrong, or what I could do right. Thank you.
Try:
scope :between, -> (me, other) { where(['(sender_id = :me and receiver_id = :other) or (sender_id = :other and receiver_id = :me)', {me: me.id, other: other.id}])}
You do not have squeel gem installed in your current project and the syntax you are using requires it. In Rails 3 you would receive an error wrong number of arguments 0 for 1, however in rails 4 you can call where without any params (so you can call not). The block you passed has been ignored and WhereChain object is returned.
Note that squeel is no longer maintained. Use with care.

How would I get the names and id's out of this object?

I have an object called #groups
When I enter #groups into the console it returns this:
[#<Group id: 2, name: "another test group", creator_id: 6, updater_id: 6, created_at: "2013-11-22 17:04:14", updated_at: "2013-11-22 17:04:14">, #<Group id: 1, name: "test group", creator_id: 6, updater_id: 6, created_at: "2013-11-20 17:50:28", updated_at: "2013-11-20 17:50:28">]
I want to make an select field and populate it with each group using the options_for_select() method
So, I was going to try to get the names and id's of each group and populate it that way but I don't know how to do this.
Rather than mapping the attributes you want out of an array, you should do this the rails way by using either the options_from_collection_for_select or, even easier, you can use collection_select in your form.
You'll want to use map for this:
#groups.map {|group| [group.name, group.id]}
This will return an array of arrays, with each containing [group.name, group.id].

How do I delete all instances of an object that has an association that has already been deleted at the command-line in Rails 3?

I have a model Comment
Comment(id: integer, body: string, notified: boolean, user_id: integer, stage_id: integer, created_at: datetime, updated_at: datetime)
A comment belongs_to : stage.
So when I assign a comment, say with ID12 to the local variable comment12 in my Rails console, I get something like this:
comment12.stage => #<Stage id: 19, project_id: 8, user_id: 1, name: "Wedding", created_at: "2011-02-25 09:05:35", updated_at: "2011-02-25 09:05:35">
However, before I setup the dependency on the associations to destroy all comments when a stage was deleted, I have some errant comments left in the db.
So how do I delete all comments, from the Rails console, that have a stage_id that no longer exists ?
Is there a quick command I can run that makes it easy to do ?
Thanks.
This should work:
Comment.joins("LEFT OUTER JOIN stages ON comments.stage_id = stages.id").where("stages.id IS NULL").each do |comment|
comment.destroy
end

Manipulating ActiveRecords using only a few attributes with Ruby on Rails

For caching matters, I'm caching an array of the attributes of the objects I need:
friends = [{:id => 4, :name => "Kevin"}, {:id => 12, :name => "Martin"}, …]
Is it possible to have a list of Users using this array, so that I can use Ruby methods? For instance, I usually get a list of non-friends with this:
non_friends = User.all - current_user.friends
Here, current_user.friends would be replaced by the cached array, only with the cached attributes:
friends = [
#<User id: 4, name: "Kevin", created_at: nil, updated_at: nil, email: nil>,
#<User id: 12, name: "Martin", created_at: nil, updated_at: nil, email: nil>,
…
]
Is it possible? Is it a good approach to caching? (a big list of ActiveRecords doesn't fit into a 1MB Memcache chunk.)
Thank you,
Kevin
edit: The idea behind this is to use a sorted/processed list of 2000 ActiveRecords around which my app heavily uses, but since it doesn't fit into a Memcache chunk, I'm trying to cache the interesting attributes only as an array. Now, how can I use this array like it was an ActiveRecord array?
Well, you can just cache the User IDs and then exclude these IDs in your finder conditions. In your example, assuming you have a friends array of hashes containing ids and names:
friend_ids = friends.map{ |f| f[:id] }
if friend_ids.empty?
non_friends = User.all
else
non_friends = User.all(:conditions => ['id NOT IN (?)', current_user.friend_ids])
end

Resources