Remove deprecated `:distinct` option from `Relation#count` for Rails 4.1 - mysql

Code:
checkin_scope.count(:select => "user_id", :distinct => true)
SQL query
SELECT COUNT(DISTINCT `checkins`.`user_id`) AS count_user_id,
location_id AS location_id
FROM `checkins` INNER JOIN `locations` ON `locations`.`id` = `checkins`.`location_id`
WHERE `checkins`.`business_id` = 452 AND `checkins`.`status` = 'loyalty'
AND `locations`.`status` = 'approved' AND
`checkins`.`location_id` IN (302825, 302838, 302839, 302901)
AND (date(checkins.created_at) between '2014-10-11' and '2014-11-11')
GROUP BY location_id
I need to remove :distinct => true as it has been removed in Rails 4.1.

Ok, I could solve the problem
checkin_scope.count("DISTINCT(checkins.user_id)")
where checkin_scope is a method,
def checkin_scope
cscope = #business.checkins.loyalty_punchh.joins(:location).where(:locations => {:status => "approved"}).group(:location_id)
cscope = cscope.for_location(#location) if #location
if #from && #to
cscope = cscope.where("date(checkins.created_at) between ? and ?",#from.to_date,#to.to_date)
end
cscope
end

Related

I am failed to retrieve data using DB:table() in laravel

I am failed to retrieve any date with this code
$data = DB::table('students')
->where([
'students.school_id' => $school_id,
'students.status' => true,
'students.class' => $request->class,
'students.section' => $request->section,
'student_attendances.date' => "'$today'",
'students.school_id' => 'student_attendances.school_id'
])
->leftJoin('student_attendances', 'students.rfid_number', '=', 'student_attendances.uid')
->get();
above code returning this query:
select * from `students` left join `student_attendances` on `students`.`rfid_number` = `student_attendances`.`uid` where (`students`.`school_id` = 1 and `students`.`status` = 1 and `students`.`class` = 1 and `students`.`section` = 1 and `student_attendances`.`date` = '2020-03-16' and `students`.`school_id` = student_attendances.school_id)
I have tried this query in mysql database and successfully getting data.
And also below code is working fine :
$sql_query_text = "select * from students left join student_attendances on students.rfid_number = student_attendances.uid where (students.school_id = student_attendances.school_id and students.status = 1 and students.class = '{$request->class}' and students.section = '{$request->section}' and date(student_attendances.created_at) = '$today')";
$data = DB::select($sql_query_text);
I could not understand what is the fault. Please help. Thank you.
the problem is
'students.school_id' => 'student_attendances.school_id'
Joint table condition can not be used in ->where() so I use
->leftJoin('student_attendances', function($join){
$join->on('students.rfid_number', '=', 'student_attendances.uid');
$join->on('students.school_id', '=', 'student_attendances.school_id');
})
And this solved my purpose

Ruby On Rails and redmine Aglie plugin fixing

Well, as maybe you know guys, in redmine base sturcture there are tables issues, projects. I never used to write code in ruby before btw. But I got task, so.
Here the issues table structure:
And here is the project table structure:
The problem is I need to get all issues where project_id equals #project and project.parent_id equals #project too.
The problem is, first I don't understand what current #project contents. Second I got no idea how to access to the #project's parent_id field here. Parent_id is referenced to the project.id field by the way.
I got ruby function here.
Boss said I need to edit scope variable. So I trying to edit it like this:
def find_no_version_issues
#backlog_version = #project.versions.open.where("LOWER(#{Version.table_name}.name) LIKE LOWER(?)", "backlog").first ||
#project.versions.open.where(:effective_date => nil).first ||
Version.open.where(:project_id => #project).order("effective_date ASC").first
#current_version = Version.open.
where(:project_id => #project).
where("#{Version.table_name}.id <> ?", #backlog_version).
order("effective_date DEcSC").first
q = (params[:q] || params[:term]).to_s.strip
#scope = (params[:scope] == "all" || #project.nil? ? Issue : #project.issues).open.visible.where(:fixed_version_id => nil).sorted_by_rank
scope = Issue.open.visible.where(:fixed_version_id => nil).where("project_id = ?", ) OR #project.or(:project_id.parent_id => #project)).sorted_by_rank
#scope = Issue.open.visible.where(:project_id => #current_version) #(:project_id => #project || #project.parent_id == :project_id || #project ).sorted_by_rank
if q.present?
if q.match(/^#?(\d+)\z/)
scope = scope.where("(#{Issue.table_name}.id = ?) OR (LOWER(#{Issue.table_name}.subject) LIKE LOWER(?))", $1.to_i, "%#{q}%")
else
scope = scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%")
end
end
#issue_count = scope.count
#issue_pages = Redmine::Pagination::Paginator.new #issue_count, 20, params['page']
#version_issues = scope.offset(#issue_pages.offset).limit(#issue_pages.per_page).all
end
So, please, could somebody help me? How could I understand, what #project contains? How could I turn query into scope?
Here's working SQL-query (or at least it got rows I need). But I really have no idea how to make this scope varible contains this data?
SELECT * FROM `issues` WHERE `project_id` IN (SELECT `id` FROM `projects` WHERE `parent_id` IS NOT NULL OR `parent_id` IS NULL ) ORDER BY `id` ASC
Well, actually I fixed this thing this way
def find_no_version_issues
q = (params[:q] || params[:term]).to_s.strip
#scope = (params[:scope] == "all" || #project.nil? ? Issue : #project.issues).open.visible.where(:fixed_version_id => nil).sorted_by_rank
#subprojects = #project.descendants.visible.all
#subprojects = #subprojects.to_a.push #project
scope = Issue.open.visible.where(project_id:#subprojects).where(:fixed_version_id => nil).sorted_by_rank
if q.present?
if q.match(/^#?(\d+)\z/)
scope = scope.where("(#{Issue.table_name}.id = ?) OR (LOWER(#{Issue.table_name}.subject) LIKE LOWER(?))", $1.to_i, "%#{q}%")
else
scope = scope.where("LOWER(#{Issue.table_name}.subject) LIKE LOWER(?)", "%#{q}%")
end
end
#issue_count = scope.count
#issue_pages = Redmine::Pagination::Paginator.new #issue_count, 20, params['page']
#version_issues = scope.offset(#issue_pages.offset).limit(#issue_pages.per_page).all
end

Operand should contain 1 column(s) ruby on rails

I have 3 model Shop Section and Price, Section have shop_id and Price have section_id
How can i show prices in Shop view?
controller/shop_controller.rb
...
def show
#metod_one = Magazine.find(params[:id])
#method_two = Section.find(:all, :conditions => ['shop_id = ?', #method_one])
#method_three = Price.find(:id, :conditions => ['section_id = ?', #method_two])
end
...
This method don't work
Mysql::Error: Operand should contain 1 column(s): SELECT * FROM prices WHERE (prices.id = '--- :id\n' AND (section_id = 5480,5482,5483,5485))
Please try the in operator:
#method_three = Price.find(:all, :conditions => ['section_id in (?)', #method_two])

Alternative as NOT IN gives a blank array

I have a query in my rails application,
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, Department.unapproved_departments ).all(:include => [:name, :project]).
Here unapproved_departments contains an array of ids in Department table.
The problem arises when unapproved_departments is a blank array.In those cases "NOT IN"
checks for ids present in the array and entire user_info is returned as a blank array.
So i would like to have all the data with ids other than those in unapproved_departments array or you can say an alternative for NOT IN
Thanx
Theres nothing wrong with NOT IN -- just that you don't want it to fire when there's nothing there.
I suggest:
user_info = Information.where("user_id = ?", user)
unapproved_departments = Department.unapproved_departments
if unapproved_departments.present? # true if not blank or nil
user_info = user_info.where("department_id NOT IN (?)", unaproved_departments)
end
user_info.all(:include => [:name, :project])
As you can see, you can chain the conditions together.
Can't you just have a special case for when unapproved_departments is empty?
if Department.unapproved_departments.empty?
user_info = Information.where("user_id = ?",user.id).all(:include => [:name, :project])
else
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, Department.unapproved_departments ).all(:include => [:name, :project])
end
it will be better if you define better unapproved_departments to retun [nil] instead of []
Oterwhise you can add [0] to your code :
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, (Department.unapproved_departments << 0) ).all(:include => [:name, :project]).
If we concentrate just on the "NOT IN" part:
user_info = Information.where("department_id NOT IN (?)", []).to_sql
# => SELECT `informations`.* from `informations` where department_id not in (NULL)
Which is weird because of null-tests: http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html
What we can do is reverse the test and get the required result:
user_info = Information.where("NOT (department_id IN (?))", []).to_sql
# => SELECT `informations`.* from `informations` where NOT (department_id in (NULL))
It works because in MySQL everything is != NULL (and also < NULL and > NULL at same time!).

Rails find :conditions

I have a Reservation model that I'm searching for with three fields. The container_id must always be self.id but as confirmed and auto_confirmed only one needs to be true. I have the following but it doesn't perform what I need:
Reservation.find(:all,
:conditions => ['container_id = ? AND confirmed = ? OR auto_confirm = ?',
self.id, true, true,])
How should I change this?
I'm not sure I'm getting your problem, but from what I understand this would work:
Reservation.find(:all,
:conditions => ['container_id = ? AND (confirmed = ? OR auto_confirm = ?)',
self.id, true, true,])
As per your question confirmed and auto_confirmed only one needs to be true. So use following
Reservation.find(:all,
:conditions => ['container_id = :container AND
( (confirmed = :flag and auto_confirm != :flag) ||
(confirmed != :flag and auto_confirm = :flag))',
{:container=> self.id, :flag=>true}]
)
I'm not sure if this is database agnostic, but you could try
Reservation.find(:all,
:conditions => ['container_id = ? AND confirmed = ? **XOR** auto_confirm = ?',
self.id, true, true,])
What you are saying is not true - a query like
SELECT * FROM foos WHERE content_id = 345 AND (confirm = 1 OR auto_confirm = 1)
will select the rows where both "confirm" columns are set to 1 (and ActiveRecord creates tinyint columns for booleans and checks against 1 and 0).
If you mean "find all rows matching on the content_id and having EITHER confirmed OR auto_confirmed true but NOT both" then you come down to a query like this
SELECT * FROM foos WHERE content_id = 345 AND ((confirmed = 1 AND auto_confirm = 0) OR (confirmed = 0 AND auto_confirm = 1))
which you reword in AR terms like this
Reservation.find(:all,
:conditions => [
'container_id = ? AND ((confirmed = 1 AND auto_confirm != 1) OR (confirmed = 0 AND auto_confirm != 1))',
self]
)
However, judging from the names your fields have you are actually implementing a state machine with separate columns which will bring you pain, so I'd investigate something that would give you progressions of states instead of checking for separate on and off bits.
I think something like this:
Reservation.find(:all,
:conditions => ['container_id = ? AND ((confirmed != true AND auto_confirm = true) OR (confirmed = true AND auto_confirm != true))',
self.id])