i have this query, which I want to se in rails way. Could please anyone help me here?
select * from users
,buyer_events
,supplier_events
where (users.id = buyer_events.buyer_id
or users.id = supplier_events.supplier_id)
and supplier_events.event_id = 11
and buyer_events.event_id = 11;
PostgreSQL
If more information is needed just write in comments :)
I guess it should be something like this:
class User
has_many :supplier_events
has_many :buyer_events
scope :with_event, ->(event_id) {
joins(:supplier_events, :buyer_events).merge(supplier_events.for_event(event_id)).merge(buyer_events.for_event(event_id))
}
end
class SupplierEvent
belongs_to :supplier, class_name: :User
belongs_to :event, class_name: :Event
scope :for_event, ->(event_id) { where(event_id: event_id) }
end
class BuyerEvent
belongs_to :buyer, class_name: :User
belongs_to :event, class_name: :Event
scope :for_event, ->(event_id) { where(event_id: event_id) }
end
Then issue:
User.with_event(11)
class User < ActiveRecord::Base
...
def self.buyers_and_suppliers user_id
joins(:buyer_events, :supplier_events).where(users: {id: user_id}, supplier_events: {event_id: 11}, buyer_events: {event_id: 11})
end
...
end
Related
I have two double joins (I believe that's what they would be considered) and it just seems awfully slow to do them separately. I know there are debates as to whether or not an individual query is quicker than multiple queries and vice versa but I am willing to try anything.
Here are my existing statements:
line_stops = OpsHeader.joins(
ops_stop_rec: :driver_header
)
.select(
:pbbname,
:pb_net_rev,
:ops_driver1,
:pb_id,
:ops_stop_id,
:dh_first_name,
:dh_last_name,
:ops_delivered_time
)
.where(
:ops_stop_rec => {
ops_arrive_time: params[:startDate] .. params[:endDate]
})
line_items = OpsHeader.joins(
ops_stop_rec: :ops_line_items
).select(
:pbbname,
:opl_amount,
:pb_id,
:ops_type,
:ops_stop_id,
:ops_order_id,
:ops_driver1,
:ops_delivered_time
)
.where(
:ops_stop_rec => {
ops_arrive_time: params[:startDate] .. params[:endDate]
}
)
Just for reference, I am pulling these from an old Firebird Database and the server hardware is not necessarily quick either, so there may be more at play than I am thinking. Also, I have to data manipulation on top of that before I serve it to the client.
Anyway, here are my associations:
class OpsHeader < ApplicationRecord
belongs_to :pb_bill
belongs_to :pb_master
has_many :ops_stop_rec, foreign_key: 'ops_order_id'
self.table_name = 'OPS_HEADER'
self.primary_key = 'pb_id'
end
class OpsStopRec < ApplicationRecord
#belongs_to :ops_order
#belongs_to :ops_im_equip
belongs_to :ops_header, foreign_key: 'pb_id'
belongs_to :driver_header, foreign_key: 'ops_driver1'
has_many :ops_line_items, foreign_key: 'opl_stop_id'
self.table_name = 'OPS_STOP_REC'
self.primary_key = 'ops_stop_id'
end
class OpsLineItem < ApplicationRecord
#belongs_to :opl_order
#belongs_to :opl_stop
belongs_to :ops_stop_rec, foreign_key: 'ops_stop_id'
self.table_name = 'OPS_LINE_ITEMS'
self.primary_key = 'opl_stop_id'
end
class DriverHeader < ApplicationRecord
#belongs_to :dh_paythru
has_many :ops_stop_rec, foreign_key: 'ops_driver1'
self.table_name = 'DRIVER_HEADER'
self.primary_key = 'dh_id'
end
What you're looking for is a union operator. There is a gem which can handle it for you.
Or try using using two left outer joins and add an OR condition.
Below is the model Structure.
class UserFamilyRole < ActiveRecord::Base
belongs_to :user_family
belongs_to :user_role
belongs_to :organization
end
class UserFamily < ActiveRecord::Base
has_many :user_family_roles
has_many :user_roles
end
I am looking for below result from the above UserFamilyRole table.
{
user_family1: [user_role1, user_role2],
user_family2: [user_role1, user_role2, user_role3]
...
}
I achieved this Result from below query:
user_family_roles = UserFamilyRole.where(:organization_id => org_id)
results = {}
juser_family_roles.each do |user_family_role|
user_family = UserFamily.find(user_family_role.user_family_id)
result[user_family.name] = user_family.user_roles.collect(&:title)
end
puts results
But Above query doesn't look optimized one so can anyone help me to write the optimized query.
In our App org_id is present.
I'm trying to do something like this:
filter_categorys = params[:filter_categorys]
companies = Company.where('id_category = (?)', filter_categorys).joins(:subsidiary).where('zone = Nuñez')
And it's not working....
So, I need to get all my companies that have an id_category and that they have at least one subsidiary within the 'zone'.
I guess this is not the way... please HELP ! :D
Company.rb:
class Company < ActiveRecord::Base
has_many :subsidiary, :foreign_key => :id_company
has_many :benefit, :foreign_key => :id_company
set_primary_key :id_company
self.table_name = 'tbl_companys'
end
Subsidiary.rb:
class Subsidiary < ActiveRecord::Base
belongs_to :company
set_primary_key :id_subsidiary
self.table_name = 'tbl_subsidiaries'
end
You have to "tell" the where clause that the zone is in the subsidiary table:
Company.where(id_category: filter_categorys).joins(:subsidiary).where(subsidiary: { zone: 'Nuñez' }
If it says "relation subsidiary was not found", try with:
Company.where(id_category: filter_categorys).joins(:subsidiary).where(tbl_subsidiaries: { zone: 'Nuñez' }
This is my code for moving data from my old database:
class Old < ActiveRecord::Base
establish_connection :old_version
self.abstract_class = true
class Recipe < self
set_table_name :recipes
has_many :uploaded_files, :as => :storage
end
class UploadedFile < self
set_table_name :uploaded_files
belongs_to :storage, :polymorphic => true
end
end
When I run the following code
Old::Recipe.all.each do |recipe|
puts recipe.uploaded_files.to_sql
end
It performs this SQL
SELECT `uploaded_files`.* FROM `uploaded_files` WHERE `uploaded_files`.`storage_id` = 38 AND `uploaded_files`.`storage_type` = 'Old::Recipe'
The problem is that I get:
`storage_type` = 'Old::Recipe'
But I need:
`storage_type` = 'Recipe'
How can I change the class for a polymorphic relationship?
The doc for has_many doesn't give me an answer.
Recently I had similar problem, this is a solution that worked for me in rails 4.2:
class Recipe < self
set_table_name :recipes
has_many :old_files, -> (object) { unscope(where: :storage_type).where(storage_type: 'Recipe') }, class_name: 'UploadedFile'
end
You have to add unscope(:where) to remove condition uploaded_files.storage_type = 'Old::Recipe' from query.
The answer by santuxus above is working properly for rails 4.2+
However, for lower versions, you could try overwriting the association like so:
class Recipe
has_many :uploaded_files, conditions: { storage_type: 'Recipe' }, foreign_key: :storage_id
end
Unfortunately, for now I found only one way to do that:
class Old < ActiveRecord::Base
establish_connection :old_version
self.abstract_class = true
class Recipe < self
set_table_name :recipes
has_many :old_files,
:class_name => 'UploadedFile',
:finder_sql => Proc.new {
%Q{
SELECT uploaded_files.*
FROM uploaded_files
WHERE uploaded_files.storage_id = #{id} AND
uploaded_files.storage_type = 'Recipe'
}
}
end
class UploadedFile < self
set_table_name :uploaded_files
belongs_to :storage, :polymorphic => true
end
end
namespace :old do
task :menu => :environment do
Old::Recipe.all.each do |recipe|
puts '~' * 50
puts recipe.id
recipe.old_files.to_a.each do |file|
puts file.storage_id, file.storage_type
end
end
end
end
very very sad
I would like to list all posts that are connected with some specific category and classroom.
I have:
class Post < ActiveRecord::Base
has_many :category_posts
has_many :categories, :through => :category_posts
has_many :classroom_posts
has_many :classrooms, :through => :classroom_posts
end
class Category < ActiveRecord::Base
has_many :category_posts
has_many :posts, :through => :category_posts
end
class CategoryPost < ActiveRecord::Base
belongs_to :category
belongs_to :post
end
class Classroom < ActiveRecord::Base
has_many :classroom_posts
has_many :posts, :through => :classroom_posts
end
class ClassroomPost < ActiveRecord::Base
belongs_to :classroom
belongs_to :post
end
And I wanna do something like this
Post.where(["category.id = ? AND classroom.id = ?", params[:category_id], params[:classroom_id]])
It indeed is very simple task, but I don't know what I should be looking for (keywords).
It's the same problem like this, but in rails.
EDIT:
I added more details to the question.
This works, but only if I have both params specified. Witch is not always the case - I dont know what params would be specified.
Post.joins(:categories, :classrooms).where(["categories.id = ? AND classrooms.id = ?", params[:classroom_id], params[:category_id]])
Category.find(params[:category_id]).posts
Also take a look at the guides:
Guides for Rails 2.35
Guides for Rails 3.0
Here is what I would do in Rails 3:
In post.rb:
def self.in_category(category_id)
if category_id.present?
join(:category_posts).where(category_posts: {category_id: category_id})
else
self
end
end
def self.in_classroom(classroom_id)
if classroom_id.present?
join(:classroom_posts).where(classroom_posts: {classroom_id: category_id})
else
self
end
end
I do not join Classroom or Category since it makes more work for DBMS and this is not required.
Now, you can do:
Post.in_category(params[:category_id]).in_classroom(params[:classroom_id])
I haven't tested it though. So do not hesitated to ask if needed.
I think that should work:
Post.joins(:category_posts, :classroom_posts)
.where(
["category_posts.category_id = ?
AND classroom_posts.classroom_id = ?", params[:category_id], params[:classroom_id]])
This will traslate to a SQL like :
SELECT
p.*
FROM
posts AS p
INNER JOIN
category_posts AS cap ON cap.id = p.category_posts_id
INNER JOIN
classroom_posts AS clp ON clpid = p.classroom_posts_id
WHERE
cap.category_id = '1' AND clp.classroom_id = '1'
;
As to whether to use :include or joins on Post look at this answer on stackoverflow.
Sounds like you need an if statment.
if params[:category_id] && params[:classroom_id]
Post.joins(:categories, :classrooms).where("classrooms.id" => params[:classroom_id], "categories.id" => params[:category_id]])
elsif params[:category_id]
Category.find(params[:category_id]).posts
else
Classroom.find(params[:classroom_id]).posts
end