How to do N: N join in rails - ruby-on-rails

user table
user.find(1)
id: 3,
name: 'hoge',
gender: 0
org_users table
user.find(1).org_users
id: 1,
org_id: 1,
user_id: 3,
status: 'in progress'
I would like to do inner join the above two tables as follows:
id: 3,
name: 'hoge',
gender: 0,
status: 'in progress'
I thought I could do it with the following command, but for some reason I can't see the result of the org_users table
User.joins(:org_users).select("org_users.*, users.*")
result:
User.joins(:org_users).select("org_users.*, users.*")
User Load (0.6ms) SELECT org_users.*, users.* FROM `users` INNER JOIN `org_users` ON `org_users`.`user_id` = `users`.`id` LIMIT 11
=> #<ActiveRecord::Relation [#<User id: 1, name: "hoge", gender: 0, created_at: "2019-12-20 14:00:38", updated_at: "2019-12-20 14:00:38">]>
SELECT org_users., users. FROM users INNER JOIN org_users ON org_users.user_id = users.id LIMIT 11
If the generated query is directly hit to mysql, the information of org_users will appear
I don't know why the two results are different.
please let me know if there is anything i misunderstood.
My source code is at the following URL
https://github.com/negabaro/railsTestJoins
The model configuration is as follows.
app/models/org.rb
class Org < ApplicationRecord
has_many :org_users
has_many :users, through: :org_users
end
app/models/org_user.rb
class OrgUser < ApplicationRecord
belongs_to :org
belongs_to :user
end
app/models/user.rb
class User < ApplicationRecord
has_many :org_users
has_many :orgs, through: :org_users
end

users = User.joins(:org_users).select('users.id, users.name, users.gender, org_users.status')
Will do the trick. It will generate something like this:
#<User:0x00005649f318dc68 id: user_id, name: name ... and so on>
You can do users.first.attributes and it will show you desired hash:
{
id: id,
name: name,
gender: gender,
status: status
}

Related

Include nested associations in JSON

# Person.rb
class Person < ActiveRecord::Base
has_many :events
end
# Event.rb
class Event < ActiveRecord::Base
belongs_to :person
has_many :tables
end
# Table.rb
class Table < ActiveRecord::Base
belongs_to :event
end
Within Person.rb I am trying to create a method to get all events and tables in one query
def complete_events
events.includes(:tables)
end
I can see in the console it is loading both events and table
Event Load (1.1ms) SELECT "events".* FROM "events" WHERE "event"."person_id" = $1 [["person_id", 17]]
Table Load (0.5ms) SELECT "tables".* FROM "tables" WHERE "tables"."event_id" IN (10)
However, the returned object is only the event records.
#<ActiveRecord::Relation [#<Event id: 1, name: "some event">]
How can I get the returned record to nested like below?
#<ActiveRecord::Relation [#<Event id: 1, name: "some event", tables: [id: 1, seats: 4, id: 2, seats: 4]>]
Edit
I am able to iterate and create a all_events object, but it not nested.
def complete_events
all_events = []
events.includes(:tables).each do |event|
all_events << event
all_events << event.tables
end
all_events
end
Use as_json:
def complete_events
as_json(
include: {
events: {
include: tables
}
)
end
try this.
User.all.as_json(methods:[:profile,:addresses])
here User is the Model, and profile and address are the mapped table having has_many or has_one associations , so the json that will be rendered will be containing the table in nested way as follows
user : {
name:"dummy name",
profile: {},
addresses: {}
}
so in one single object you will have all the data and the associated data.

STI and preload relations

I have next models:
class User < ActiveRecord::Base
end
class Customer < User
has_many :orders, foreign_key: 'customer_id', dependent: :destroy
end
class Translator < User
has_many :orders, foreign_key: 'translator_id'
end
class Order < ActiveRecord::Base
belongs_to :customer, class_name: "Customer"
belongs_to :translator , class_name: "Translator"
end
And I have an issue when I try to load orders with translator and customer , like this:
Order.eager_load(:vox_logs,:customer, :translator)
In this case customer will be loaded fine but translator not:
order.translator = nil
order.translator_id = 123
How can I fix it?
EDIT:
I added console output for more clear (it's from a order's function):
(byebug) translator
nil
(byebug) translator_id
637
(byebug) Translator.find translator_id
Translator Load (70.1ms) SELECT "users".* FROM "users" WHERE ((users.roles_mask & 4) > 0) AND "users"."id" = $1 LIMIT 1 [["id", 637]]
<Translator id: 637, email: nil, first_name: nil, middle_name: nil,
last_name: nil, native_language: "fr", country: "RU", city: "Липецк"...

Rails join or includes?

I've got a User model/table and a Friend model/table. The users table has a uid column that stores a user's Facebook uid. The friends table stores their Facebook friends (associated by a user_id column).
How can I query all of a specific user's friends who have an account in the users table? In other words - I want the user models returned for user 13's friends who have signed up (exist in the users table).
My models for same problem
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, through: :friendships
# ...
end
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User', :foreign_key => 'friend_id', :primary_key => 'facebook_id'
end
Assuming you the user of interest is referenced by #user:
User.joins("inner join friends on friends.uid = users.uid")
.where("friends.user_id = ?", #user.id)
There is probably a more "railsy" way to do this that makes better use of arel.
If I have the models:
class User < ActiveRecord::Base
attr_accessible :name, :uid
has_many :friends
end
class Friend < ActiveRecord::Base
attr_accessible :uid
belongs_to :user
belongs_to :account, foreign_key: 'uid', primary_key: 'uid', class_name: 'User'
end
then I can do:
u=User.create(name: 'Alice', uid: 'fb1')
u2=User.create(name: 'Bob', uid: 'fb2')
u.friends.create(uid: 'fb2') # add Bob as friend
u.friends.create(uid: 'fb9') # add someone as friend
Now
u.friends # gives all friends
Friend Load (0.3ms) SELECT "friends".* FROM "friends" WHERE "friends"."user_id" = 4
=> [#<Friend id: 3, user_id: 4, uid: "fb2">, #<Friend id: 4, user_id: 4, uid: "fb9">]
u.friends.joins(:account) # only friends having an account
Friend Load (0.2ms) SELECT "friends".* FROM "friends" INNER JOIN "users" ON "users"."uid" = "friends"."uid" WHERE "friends"."user_id" = 4
=> [#<Friend id: 3, user_id: 4, uid: "fb2">]
while includes doesn't do an inner join and gives all friends:
u.friends.includes(:account)
Friend Load (0.2ms) SELECT "friends".* FROM "friends" WHERE "friends"."user_id" = 4
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."uid" IN ('fb2', 'fb9')
=> [#<Friend id: 3, user_id: 4, uid: "fb2">, #<Friend id: 4, user_id: 4, uid: "fb9">]

creating instance of belongs_to model not showing up in it's associated objects list

I've created two models with the below associations
class User < ActiveRecord::Base
has_many :roles, :dependent => :destroy
end
class Role < ActiveRecord::Base
belongs_to :user
end
class Student < Role
end
class Tutor < Role
end
However when I create a new child role, I assume it would get associated to the model it has the belongs to for.
Such as:
Tutor.create(:user_id => user_id)
I would expect:
#some user #user
#user.roles
to have an array containing a Tutor. However, it doesn't seem to be working. Any ideas what I'm doing wrong?
Once you start using Single Table Inheritance, than the Tutor that you created isn't a role, as far as active-record is concerned for this type of query.
class User < ActiveRecord::Base
has_many :roles
has_many :tutors
end
#user = User.first
#user.roles
=> []
#user.tutors
=> [#<Tutor id: 1, user_id: 1, type: "Tutor", created_at: "2012-10-26 18:15:16", updated_at: "2012-10-26 18:15:16">]
If you want to get a list of all roles that your users may have:
Role.where(user_id: #user.id).all
[#<Tutor id: 1, user_id: 1, type: "Tutor", created_at: "2012-10-26 18:15:16", updated_at: "2012-10-26 18:15:16">, #<Student id: 2, user_id: 1, type: "Student", created_at: "2012-10-26 18:18:32", updated_at: "2012-10-26 18:18:32">]

Rails, can't load data from fixtures that have HABTM relationshionship

I'm new to rails and testing and have a problem with loading my fixtures.
payment.yml
payment:
name: something
amount: 1.5
event: some_event
user: some_user
description: long text
users: some_user, some_user2
users.yml
some_user:
email: test#test.com
nick: name
some_user2:
email: test#test.com
nick: name
okey, so the problem is that when I'm doing the functionaltest for creating a payment
test "should create payment" do
assert_difference('Payment.count') do
post :create, :payment => #payment.attributes
end
it just sends
< Payment id: nil, name: "something", amount: 1.5, event_id: 972288058, user_id: 63246679, created_at: "2010-11-05 19:56:53", updated_at: "2010-11-05 19:56:53", description: "long text" >
and not the users array with multiple users. I use the "user" to define who owns the payment and users (in a seperate join table) as a list of users sharing the payment.
Any idea what I'm doing wrong?
here is the model for payments
class Payment < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
belongs_to :event
belongs_to :user
has_and_belongs_to_many :users
end
Can you put the model for payment? I had something similar and the problem was that the model was different. For example, if it's a ActiveRecord class, you have to check how it and its relationships. For example, if the event is actually an "event_id" that belongs_to an "event" class, then you should put something similar to this:
payment.yml
payment:
name: something
amount: 1.5
event_id: 1
user_id: 1
...
user.yml
id: 1
name: David Smith
status: Branch Manager
...
event.yml
id: 1
name: overdraft charge

Resources