Rails query user first name on join model - mysql

this situation that find the user on a join model is seems tricky than usual
class ConversationParticipant < ActiveRecord::Base
belongs_to :user
belongs_to :conversation
attr_accessible :user_id
end
class User < ActiveRecord::Base
has_many :conversation_participants
end
I'm trying to find the conversation_participant with the fisrt_name with this query
user = User.where('conversation_participant like ? or first_name like ?', query, query)
but the query did not return the user_participant and the user first_name either.
someone can spare a hint please!

You have to include the % for the sql LIKE operator
query = params[:query] # or something ...
User.where('conversation_participant LIKE :query OR first_name LIKE :query', query: "%#{query}%")

Related

Run mysql query from a controller in ruby on rails

I need run a mysql query from the controller but I do not know how to connect to db.
this is my method:
def set_dcs
sql="select employees.nombre, employees.apellido_paterno, employees.apellido_materno from employees, activities, field_tests
where activities.field_test_id=field_tests.id and employees.id=activities.dcs_id and field_tests.id=id"
end
How do I get the result of the query?
How could I do the same query but with the ActiveRecord?
You can execute raw SQL through ActiveRecord::Base.connection but I rarely recommend it and certainly not in this case, but for edification purposes
def set_dcs
sql= <<SQL
select employees.nombre, employees.apellido_paterno, employees.apellido_materno
from employees, activities, field_tests
where activities.field_test_id=field_tests.id and employees.id=activities.dcs_id and field_tests.id=id
SQL
ActiveRecord::Base.connection.exec_query(sql)
end
I was not sure what the trailing id is in reference to and it will raise a SQL error due to it's ambiguity. I am going to assume it is a parameter and the primary search condition where as the rest are table joins.
That being said since you are using rails these can be true associations and joins resulting in far more readable controller code e.g. Model Definitions
class Employee < ActiveRecord::Base
has_many :activities, foreign_key: :dcs_id
has_many :field_tests, through: :activities
end
class FieldTest < ActiveRecord::Base
has_many :activities
end
class Activity < ActiveRecord::Base
belongs_to :employee, foreign_key: :dcs_id
belongs_to :field_test
end
Then the controller is simply
Employee.
select("employees.nombre, employees.apellido_paterno, employees.apellido_materno").
joins(:field_tests).where(field_tests: {id: SOME_ID})
the resulting SQL will be similar to
SELECT
employees.nombre,
employees.apellido_paterno,
employees.apellido_materno
FROM
employees
INNER JOIN activities ON employees.id = activities.dcs_id
INNER JOIN field_tests ON activities.field_test_id = field_tests.id
WHERE
field_tests.id = SOME_ID
And this will return a collection of Employee Objects rather than an ActiveRecord::Result (returned from ActiveRecord::Base.connection.exec_query) which is more similar to an Array than anything else.

Rails 5 - Activerecord association query

I have two models associated with each other as follows.
class Comment < ApplicationRecord
belongs_to :user
end
class User < ActiveRecord::Base
has_many :comments
end
Following record query
comments_list = Comment.where(:post_id => post_id, :is_delete => false).joins(:user).select('comments.*,users.*')
Generates the following mysql query in logger
SELECT comments.*,users.* FROM `comments` INNER JOIN `users` ON `users`.`id` = `comments`.`user_id` WHERE `comments`.`post_id` = '81' AND `comments`.`is_delete` = 0.
This seems generating very ligitimate query, but comments_list object contain columns only from comments table.
Thanks
It depends on what you want to do, if you want to display the username next to the comment, Mert B.'s answer is fine, all you have to do is include(:user) and the users from the comment list will be fetched along when you do something like this:
comments_list = Comment.where(:post_id => post_id, :is_delete => false).joins(:user).select('comments.*,users.*')
comments_list.each do |comment|
puts "#{comment.text} by #{comment.user.name}"
end
Or maybe if you want only users who have at least one comment, you can always select users from the user_ids on the comments table:
User.where(id: Comment.select(:user_id))

Write an ActiveRecord association statement for Inner Join query

There are three table namely attendances,students and subjects for which I am unsuccessfully trying to do build an inner join query using active record.
Desired sql query
The raw sql statement that fetches correct data is
SELECT * FROM attendances AS a
INNER JOIN subjects AS b ON a.subject_id = b.id
WHERE b.organization LIKE '%city%'
AND a.started_at BETWEEN '2016-07-11 02:59:00' AND '2016-07-11 09:00:00'
The above query fetches exactly the correct 30 rows. However the problem arises when I try to perform the same with active-record associations.
Active-record associations
ActiveRecord::Base.establish_connection ({ adapter: 'mysql2',host:'localhost',
username: 'testuser',password: '***',database: 'database'})
class Subject < ActiveRecord::Base
has_many :attendances
has_many :students, through: :attendances
end
class Student < ActiveRecord::Base
has_many :attendances
has_many :subjects, through: :attendances
end
class Attendance < ActiveRecord::Base
belongs_to :subject
belongs_to :student
end
data = Attendance.
where(started_at: start_date..end_date).
joins(:subject).
where(subjects: {:organization => city}).
pluck(:subject_id,:name,:duration,:started_at,:student_id)
Using _to_sql_ and after removing the :pluck, the sql query generated by active record is
SELECT `attendances`.* FROM `attendances` INNER JOIN `subjects`
ON `subjects`.`id` = `attendances`.`subject_id`
WHERE (`attendances`.`started_at` BETWEEN '2016-07-11 02:59:00'
AND '2016-07-11 09:59:00')
AND `subjects`.`organization` = 'city'
Modifying the statement to the below one doesn't help either.
data = Attendance.joins(:subject).
where('started_at BETWEEN ? AND ?','2016-07-11 02:59:00','2016-07-11 09:59:00').
where(subjects: {:organization => 'city'}).
pluck(:subject_id,:name,:duration,:started_at,:student_id)
The sql query generated for the above statement after removing :pluck using _to_sql_ as suggested is
SELECT `attendances`.* FROM `attendances` INNER JOIN `subjects`
ON `subjects`.`id` = `attendances`.`subject_id`
WHERE (started_at BETWEEN '2016-07-11 02:59:00' AND '2016-07-11 09:59:00')
AND `subjects`.`organization` = 'city'
Both the above active-record statement results in additional irrelavent rows being fetched. I am unable generate the desired correct sql query as shown earlier.
Constructing a correct active record statement or associations would be really helpful.
environment:-
ruby 2.1.6
activerecord 4.2.4

Rails search through `has_many :through` text fields

Let say I have a two models with association has_many :through between them.
class Category < ActiveRecord::Base
has_many :category_recipes
has_many :categories, through: :category_recipes
validates :name, presence: true
class Recipe < ActiveRecord::Base
has_many :category_recipes
has_many :categories, through: :category_recipes
validates :title, presence: true
I want to create search functionality using ActiveRecord for mySQL database, which allow users to implement text search on Recipe title and Category name.
Now I have just:
#recipes = Recipe.where('title LIKE ?', "%#{params[:query]}%")
How can I modify this query to search through both title of recipe and it's category names?
Recipe.includes(:categories).where('recipes.title LIKE :query or categories.name like :query', query: "%#{params[:query]}%").references(:categories)
See: Specifying Conditions on Eager Loaded Associations
Hey try in this way
#recipes = Recipe.includes(:categories).where('title LIKE ? or categories.name LIKE ?', "%#{params[:query]}%","%#{params[:query]}%")
You need to left join to the associated table and query the name on either table with OR:
Recipe.joins("LEFT OUTER JOIN category_recipes ON category_recipes.recipe_id = recipes.id")
.joins("LEFT OUTER JOIN categories ON categories.id = category_recipes.id")
.where("recipes.title LIKE :q OR categories.name LIKE :q", q: "%#{params[:query]}%").uniq

Custom Search in Ruby on Rails

I'm trying to implement a custom search feature in my Rails app.
I have 3 tables User Company and CompanyUser
My relations declared are as follows
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
...
end
In Company.rb
has_many :company_users, dependent: :destroy
has_many :users, through: :company_users
In User.rb
has_many :company_users, dependent: :destroy
has_many :companies, through: :company_users
and in my view page I'm listing all companies using company_users table
Now i have a search field where I can type a name in it which filters this list of company users.
I'm calling a method from my CompanyUsers table to filter the search result like this
#company_users = CompanyUser.all
if params[:search_data].present?
#company_users = #company_users.filter_company_users(params[:search_data])
end
where params[:search_data] is passed to the same method when search data is entered in the search field.
this is the method that do the search filtering.
def self.filter_company_users(search_data)
where('company_id like (?)', "%#{search_data}%")
end
Right now I can get the result only if I type the correct id of CompanyUser table in that search field. What I'm trying to do is to search using fields from User table and Company Table. For eg email from User and name from Company.
class CompanyUser
def self.search(search_data)
search = self.joins(:company, :user)
search.where!('company_users.company_id LIKE :query OR users.email LIKE :query OR companies.name LIKE :query', query: "%#{search_data}%")
search
end
end
With the join statement you join the CompanyUser table with the company and the user, therefore you will be able to apply filters on that tables too.
The where condition reuses the same query string and applies the search in OR to all the columns you want to search for.
#company_users = CompanyUser.all
#copany_users.all(:conditions => ["company_id LIKE ? OR company.email like ? OR user.name LIKE ?","%#{params[:search_data]}%","%#{params[:search_data]}%", "%#{params[:search_data]}%" ])
or
def self.filter_company_users(search_data)
where("company_id LIKE ? OR company.email like ? OR user.name LIKE ?" ,"%#{search_data}%", "%#{search_data}%","%#{search_data}%")
end