How do I search an id in a string attribute (SQL) - sql

In my chat app I want to calculate the response rate for student model.
I track all conversations with a slug attribute. It's a string like this: 270-77, which means that this is a conversation between student 270 and recruiter 77.
Now I want to check how many conversations one student has. Here is my code:
def calculate_number_of_conversations(#student)
#conversations = Conversation.where("slug LIKE ?", "%#{params[#student]}")
end
Important is that it should only search in the first part of the string because the first number in slug is always a student's id.

I'm not sure what #student is. I will write my examples as if it's a record.
You could use - to make sure it's looking for students only:
#conversations = Conversation.where('slug LIKE ?', "#{#student.id}-%")
But I think it's better to have explicit relationships:
class Conversation < ApplicationRecord
belongs_to :student
belongs_to :recruiter
end
#conversations = #student.conversations

You can add the '-' to the WHERE LIKE clause:
def calculate_number_of_conversations(#student)
#conversations = Conversation.where("slug LIKE ?", "%#{params[#student]}-")
end

Related

Select users whose last associated object was created less than x days before

I am building a Rails 4.2.7.1 which uses Postgres database and I need to write a feature for certain group of users.
class User < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
belongs_to :user
end
I need to select users from certain location who have exactly one payment and I also need to be able to pick users whose payment created_at attribute is exactly x
I tried
location.users
.without_deleted
.where(num_payments: 1)
.joins(:payments)
.where('payments.user_id = users.id').order('created_at
DESC').where("payments.created_at < ?", Date.today).group('users.id')
but it did not give me expected results.
Thanks!
You should start from User since this is what you want at end, and take joins with payments since you want to query it along.
User.joins(:payments)
.where(location_id: location.id, num_payments: 1)
.where(payments: { created_at: Date.today })

Rails - Search for object based on association's value

I've got two models Company and InsuredObject. Company has_many InsuredObjects and the reverse belongs_to. Currently, I have a functioning search for InsuredObject(s) that returns all objects that contain the search input as shown below:
# /models/insured_objects.rb
def self.search(search)
query = "%#{search}%"
if search
where("object LIKE ? OR insurance_type LIKE ? OR class_code LIKE ? OR information LIKE ?",
query, query, query, query)
end
end
and:
# /controllers/insured_objects_controller.rb
def index
#insured_objects = InsuredObject.search(params[:search])
end
Each Company has a is_active attribute. I'm trying to think of a way to search for the same thing but only return InsuredObject(s) that their Company's is_active attrutbute is true. Any thoughts?
Get all entries of InsuredObject from active companies:
InsuredObject.joins(:company).where(companies: {is_active: true})
In joins(:company), :company is a name of association (in InsuredObject you should have belongs_to :company)
In where(companies: ..., :companies is a table name for model Company

Rails 4 - query on association count is greater than an attribute

I want to do something like "Find all Books where book.pages.count < books.max_pages".
So the models are:
class Book
has_many :pages
end
class Page
belongs_to :book
end
I know I can find books w/ a set number of pages. eg:
# Get books w/ < 5 pages.
Book.joins(:pages).group("books.id").having("count(pages.id) < ?", 5)
Is there a good way to do this with a dynamic page count? eg:
Book.joins(:pages).group("books.id").select(.having("count(pages.id) <= book.max_pages")
If not I can always just store something inside the Book model (eg book.is_full = false until a save causes it to be full), but this is a bit less flexible if max_pages gets updated.
You could create a scope like this:
def self.page_count_under(amount)
joins(:pages)
.group('books.id')
.having('COUNT(pages.id) < ?', amount)
end
UPDATE
This should work if max_pages is an attribute of the Book model.
def self.page_count_under_max
joins(:pages)
.group('books.id')
.having('COUNT(pages.id) < books.max_pages')
end
Use counter_cache!
http://guides.rubyonrails.org/association_basics.html 4.1.2.3 :counter_cache

Using where clause with a foreign key

In my app I have a search field to find football visits. I want it to be able to search by the club of the visit. In my model visit belongs_to club, so visit has a field "club_id". So when I search with an ID, it finds the club, but I want to be able to find it by club name. "club_id" should be replaces by something like "visit.club.name", but how can I achieve this? This is my current query:
# Find visits
def find_anything(find_phrase)
unless find_phrase.blank?
#visits = Visit.where('address LIKE ? OR ground LIKE ? OR club_id LIKE ?',
"%#{find_phrase}%",
"%#{find_phrase}%",
"%#{find_phrase}%")
end
end
that should do the trick:
Visit.where(club_id: Club.where(name: "ClubName"))
Club.joins(:visits).where('visits.club_id' => club_id).first.name
*this assumes the Club model has_many :visits
or
Club.find(Visit.find_by_club_id(club_id)).name

Complex Query with Has many and belongs to for RAILS 3

I am trying to do a QUERY in my controller to get a list of suppliers with a category ID.
I have my models set up like this.
class Supplier < ActiveRecord::Base
has_and_belongs_to_many :sub_categories
end
class Category < ActiveRecord::Base
has_many :sub_categories
end
class SubCategory < ActiveRecord::Base
belongs_to :category
has_and_belongs_to_many :suppliers
end
A supplier can have Many sub_categories that are under one single category. So i can grab the category of a supplier by doing this.
#supplier.sub_categories.first.category.name
This returns the category that the supplier comes under because they have to have at least 1 sub category which is then linked to a category.
What i am trying to do is by passing a category_id i wish to return all suppliers that come under that category.
I had it written like this but it doesnt seem to be working.
#category = Category.find(params[:category_id])
#suppliers = Supplier.where('sub_category.first.category.id = ?', #category.id)
i get the following sql error
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.id = 20)' at line 1: SELECT `suppliers`.* FROM `suppliers` WHERE (sub_category.first.category.id = 20)
Well, that's certainly an sql error. The stuff inside the where() call gets translated directly to SQL, and that's not sq;l. :)
You need to join tables together. I'm assuming there's a sub_category_suppliers table that completes the habtm association. (BTW, I much prefer to use has_many :through exclusively)
I think it would be something like this:
Supplier.joins(:sub_category_suppliers => :sub_categories).
where('sub_categories.category_id =?', #category.id).
group('suppliers.id')
As Caley Woods suggested, this should be placed in the Supplier model as a scope:
scope :by_category, lambda { |category_id|
joins(:sub_category_suppliers => :sub_categories).
where('sub_categories.category_id =?', category_id).
group('suppliers.id')
}
and then called as Supplier.by_category(#category.id)