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.
Related
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!
I am trying iterate through following active record
#<ActiveRecord::Relation [#<WantedEquipment id: 1, identifier: "WEID-0000001", title: "Wanted a Test Equipment", category_id: 1, sub_category_id: 3, listing_type: nil, description: "This is a test wanted equipment.", name: "John", email: "john.user#mailinator.com", user_id: nil, status: 1, created_at: "2017-02-25 16:10:35", updated_at: "2017-02-25 16:10:35">, #<WantedEquipment id: 2, identifier: "WEID-0000002", title: "Wanted a Test Equipment1", category_id: 1, sub_category_id: 3, listing_type: nil, description: "This is a test wanted equipment.", name: "John", email: "john.user#mailinator.com", user_id: nil, status: 1, created_at: "2017-02-25 16:10:50", updated_at: "2017-02-25 16:10:50">]>
To collect the values of column email. I am quiet new to ruby.
I ran the following on rails console.
WantedEquipment.all.each do |eq|
eq.email
end
As a result I got the whole table again instead of just the emails. Could somebody please guide me here?
If all you need are the email addresses and not the actual AR objects, then use this:
WantedEquipment.pluck(:email)
This will translate into the following SQL:
SELECT "wanted_equipments"."email" FROM "wanted_equipments"
You can select all email using following way
WantedEquipment.select('email')
If possible always use database level memory instead of system.
You can use either select or pluck here.
WantedEquipment.pluck(:email)
Or
WantedEquipment.select(:email)
Depends upon your result set performance you can use anyone.
My project is hosted on Heroku.
I was surprised when Room.all method returned objects with first object with ID 2 and only then a second object with ID 1. I thought that there were some sort of guarantee that objects are returned already ordered by ID. Should I always call Room.all.order(:id) instead of regular all method?
irb(main):002:0> Room.all
=> #<ActiveRecord::Relation [
#<Room id: 2, color: "rgb(83, 180, 83)", status: "Status #2", created_at: "2014-10-11 14:14:02", updated_at: "2014-10-11 14:18:19">,
#<Room id: 1, color: "rgb(0, 96, 255)", status: "Status #3", created_at: "2014-10-11 14:14:02", updated_at: "2014-10-11 14:18:30">
]>
Nope. Room.all just ends up with the SQL SELECT * FROM rooms; - no order is there. In this event, the order of the records is determined by the database (for instance, in PostgreSQL, I notice it returns me the most recently updated records last).
If you want to ensure there's an order when you call .all, add a default scope which adds it:
default_scope order('rooms.id ASC')
I'm using Closure_Tree gem and one of its instance methods, tag.descendants, returns a scope of all children, children's' children.
**tag.descendants** returns a scope of all children, childrens' children, etc., excluding self ordered by depth.
My questions are:
What is scope? Is it different from the name_scope?
It seems like the tag.descendants method is returning a hash. Please correct me if I'm wrong. And how can I access and return the name values?
This is what I received from rails console:
2.0.0-p353 :010 > #tag.descendants
Tag Load (0.5ms) SELECT "tags".* FROM "tags" INNER JOIN "tag_hierarchies" ON "tags"."id" = "tag_hierarchies"."descendant_id" WHERE "tag_hierarchies"."ancestor_id" = ? AND ("tags"."id" != 1) ORDER BY "tag_hierarchies".generations asc [["ancestor_id", 1]]
=> #<ActiveRecord::AssociationRelation [#<Tag id: 4, name: "Drinks", created_at: "2014-01-25 09:53:20", updated_at: "2014-01-25 09:53:20", parent_id: 1>, #<Tag id: 5, name: "Alcoholic", created_at: "2014-01-25 16:12:43", updated_at: "2014-01-25 16:12:43", parent_id: 4>, #<Tag id: 6, name: "Non-Alcoholic", created_at: "2014-01-25 16:14:13", updated_at: "2014-01-25 16:14:13", parent_id: 4>]>
2.0.0-p353 :011 >
I would like to know how I could call the name values of all the descendants. I've tried #tag.descendants.name but it returned "tag".
2.0.0-p353 :011 > #tag.descendants.name
=> "Tag"
Scopes are what allow you to take one big Active Record object and split it up into small different parts. For example you can scope projects so that user A can only see project A and user B can only see Project B, while all projects are on the project table. Check out the api it may clear things up about how you set a scope http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-scope
#tag.descendants.pluck(:name)
the reason #tag.descendants.name doesn't work is because you are calling the name method on a collection of decendants and it doesn't know which name to give you.
I have this strange behavior and I don't undertand why. Here is the thing:
I have this record in my payment model:
1.9.3p286 :019 > u.payment.last
Payment Load (0.3ms) SELECT "payments".* FROM "payments" WHERE "payments"."user_id" = 10
=> [#<Payment id: 37, bank_name: "Mercantil", plan: "Plan Uno", date: "2012-12-25", reference_number: "3452435", coupon: "", user_id: 10, created_at: "2012-12-25 21:56:12", updated_at: "2012-12-25 21:58:31", active_until: "2013-01-24">]
As you can see, I have one record for my user: 10.
If I try to get the same information in my controller I don't get any exception, but
#user.payment.last.active_until
is empty, the same in the view.
For example if I try this in my view:
<%= #user.payment.last.active_until %>
I didn't get anything, is blank.
If I try this
<%= #user.payment %>
I got the same as my console
[#<Payment id: 37, bank_name: "Mercantil", plan: "Plan Uno", date: "2012-12-25", reference_number: "3452435", coupon: "", user_id: 10, created_at: "2012-12-25 21:56:12", updated_at: "2012-12-25 21:58:31", active_until: "2013-01-24">, #<Payment id: nil, bank_name: nil, plan: nil, date: nil, reference_number: nil, coupon: nil, user_id: 10, created_at: nil, updated_at: nil, active_until: nil>]
I really don't understand what happend here. Any help please.
Thanks in advance.
PD: The user could has many payments, but I need just the last.
It's not the same as in your console. In the console you get have one record, but in the view you get two - the record that you see in the console, and another blank one.
I'm guessing the blank one is the one that you are using for the form tag helper for the form used to create a new Payment record, but that's also the one that last returns. Either take the one before last, or filter for saved records before you call last.