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.
Related
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}%")
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
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
I need to write a MySQL join query for the following scenario.
I have a answers table which has id, score, student_id, tests_passed, created_at, problem_id.
I have a problem table, which has an id, assignment_id.
I have a assignments table, which has an id, title and other fields.
Each answer belongs to a problem. In the answer table, I can retrieve all the answers to a problem by using the problem_id.
Each problem belongs to an assignment. I can retrieve all the problems of an assignment, using the assignment_id in the problems table.
I need to retrieve the final best score of a student in a problem for an assignment.
Is there a way to achieve this without using multiple queries.
Considering these relations:
class Answer < ActiveRecord::Base
belongs_to :student
belongs_to :problem
class Problem < ActiveRecord::Base
belongs_to :assignment
has_many :answers
class Assignment < ActiveRecord::Base
has_many :problems # or has_one, whatever
class Student < ActiveRecord::Base
has_many :answers
has_many :problems, through: :answers # You might not have this relation configured
You could do:
scope = Student.includes(answers: { problems: :assignment })
scope = scope.where(problems: { title: '3x + 2 = 12' })
scope = scope.where(students: { name: 'Johnny' })
scope = scope.where(assignment: { id: my_assignment_id })
scope = scope.select('MAX(score), *') # not sure about this part, depending on your needs
To view all students best assignment score for a given assignment/problem this should work:
select student_id, problem_id, assignment_id, max(score) from answers
join problem on answers.problem_id = problem.id
join assignments on problem.assignment_id = assignments.id
where assignment_id = <your assignment param>
and problem_id = <your problem param>
and answers.id = <your answers id>
group by student_id
However you should be able to do away with the assignment_id param assuming a problem is unique to a single assignment.
I am totally new to Ruby on Rails and I am trying to search through some relational database tables, I am trying to search for a given ID number in a Customer table then from the results look at who the sales_rep for that customer is. With this
#salesrepcust = Customer.find(:all, :conditions => ["id = ?",#data])
I am able to get back the correct customer given there ID number but I dont see how in ruby on rails to then pull from those results just one column value, in this it would be the value for sales_rep, and then use that as my #result for
#salesrepcustdata = Salesrep.find(:all, :conditions => ["id = ?", #result])
I have searched for this but i guess im not wording it correctly because i am not able to find anything specifically on this, can anyone help?
It's pretty straightforward to select a single column; you can try something like this:
#salesrepcustids = Customer.where(id: #data).select(:id)
This will generate a SELECT id FROM ... statement.
And now you can do this:
#salesrepcustdata = Salesrep.where(id: #salesrepcustids)
This will generate an SELECT...IN statement with those ids.
(You might find it easier to set up proper ActiveRecord has_many and belongs_to relationships in your models, or whatever relationship is appropriate.)
Assuming the sales rep is represented in the Customer table as sales_rep_id you can just do:
Salesrep.find(Customer.find(#data).sales_rep_id)
The find method assumes you're looking for id and if there's just one item with that id, there's no need to specify :all.
This is all discussed in http://guides.rubyonrails.org/active_record_querying.html
That Customer query could be simplified to just:
#customer = Customer.find(#data)
You don't mention if you've setup a relationship between Customer and Salesrep but here goes:
# app/models/customer.rb
class Customer < ActiveRecord::Base
belongs_to :salesrep, class_name: 'Salesrep' # => the customers table should have a salesrep_id column
end
# app/models/salesrep.rb
class Salesrep < ActiveRecord::Base
has_many :customers
end
customer_id = 1
#customer = Customer.find(customer_id)
#salesrep = #customer.salesrep
# from the other way, assuming you need both the salesrep and customer:
salesrep_id = 10
#salesrep = Salesrep.find(salesrep_id)
# the following will only find the customer if it's owned by the Salesrep
#customer = #salesrep.customers.find(customer_id)