Select attributes from multiple tables with no association - ruby-on-rails

If could really help me out with problem I have, I would really appreciate it. My problem is that I can not select attributes from certain tables that have no association between them.
To explain myself better, here are my models:
class User < ActiveRecord::Base
has_many :measurement_blocks
has_many :measurements, through: :measurement_blocks
end
class MeasurementBlock < ActiveRecord::Base
belongs_to :user
has_many :measurements
end
class Measurement < ActiveRecord::Base
belongs_to :measurement_block
end
class Device < ActiveRecord::Base
has_many :measures
end
class Measure < ActiveRecord::Base
belongs_to :device
end
I can get a ProxyAssociation with
user.measurements
but what I really want is to include the device and measures names.
I have tried the following:
measurements = user.measurements
measurements.include("INNER JOIN ON devices (devices.id = measurements.device_id)")
but it does not work. Furthermore, as I mentioned before I want to
include the measures and devices names along with the measurements.
ActiveRecord is frustrating to me when there is no full association between models.
Thank you again.

Related

Find records based on its other parent child

I have this associations:
class Ship < ApplicationRecord
has_many :captain_profiles
has_many :captains, through: :captain_profiles
end
class CaptainProfile < ApplicationRecord
belongs_to :captain
belongs_to :ship
end
class Captain < ApplicationRecord
has_one :captain_profile
has_many :schedules
end
class Schedule < ApplicationRecord
belongs_to :captain
end
And I need list of all ships that are ready to be taken to the sea. In other words I have to find all ships that has at least one Captain with at least one of his schedules.
I thought about merging two inner joins as I need Ships which has Captains which has Schedules.
I tried Captain.includes(:schedules).where("schedule.id IS NOT NULL") and so with Ships but it does not work. Could someone explain me what am I doing wrong and how shall I do this?
Simply use joins which generates INNER JOIN.
Ship.joins(captains: :schedules)

Multiple HMT associations vs. a top level association

I have four interrelated models: restaurants, menus, sections, and dishes. The dishes have_and_belong_to_many sections and ultimately are at the very bottom of the association chain. In my app I often need to reference the restaurant of the dish multiple times.
I know to accomplish this I'd need create a cascade of HMT associations. My question is, is it ideal to setup a belongs_to relationship between a restaurant and dish to avoid the multiple queries or leave as is? As of now this just feels dirty (may just be me though).
class Restaurant < ApplicationRecord
has_many :menus, dependent: :destroy
has_many :dishes, through: :menus
end
class Menu < ApplicationRecord
has_many :sections, dependent: :destroy
has_many :dishes, through: :sections
belongs_to :restaurant
end
class Section < ApplicationRecord
belongs_to :menu
has_and_belongs_to_many :dishes
end
class Dish < ApplicationRecord
has_and_belongs_to_many :sections
end
The denormalization you propose here seems reasonable to me given your use case. As always, the performance gains of denormalization must be weighed against the complexity it introduces, especially the need to write code to ensure that a the restaurant a dish belongs to is always the same restaurant its section's menu belongs to.
I guess my approach would be: Retain the normalized data model until you have an actual performance problem that needs to be addressed. Then you can consider denormalizing to address it.
While you are still have the cascade of HMTs, consider writing delegators to make the code as clean as if you had a direct restaurant-dish association. I'm thinking:
class Dish < ApplicationRecord
delegate :restaurant, to: :section
end
class Section < ApplicationRecord
delegate :restaurant, to: :menu
end
Then you can do:
dish.restaurant

Duplication of models with multiple nested & non-nested belongs_to relationships

Apologies if the title isn't accurate, I had a difficult time distilling this question into a single line. I'm using the amoeba gem and trying to figure out if it's possible to associate a duplicated model with multiple belongs_to relationships.
For instance:
class Building < ActiveRecord::Base
has_many :floors
has_many :layout_groups
end
class Floor < ActiveRecord::Base
belongs_to :building
has_many :units
end
class Unit < ActiveRecord::Base
belongs_to :floor
has_many :layouts
end
class Layout < ActiveRecord::Base
belongs_to :unit
belongs_to :layout_group
end
class LayoutGroup < ActiveRecord::Base
belongs_to :building
has_many :layouts
end
As you can see, Layouts belongs to both Unit and LayoutGroup. If I'm making a complete duplicate of Building, how do I associate layouts with both units and layout_groups but also ensure that two sets of layouts are not created in the process?
Im open to using a non-amoeba solution, I just stated there as it was suggested.

Rails 4 using multiple association to generate a filtered association

I have a interesting association in Rails 4.1 I am trying design and can't seem to come up with the right way to do it, so thought I would ask for help.
Essentially, we have four models that matter: Family, ActivityTemplate, Device and DeviceType. A Family has many Devices, Device belongs_to a DeviceType, and ActivityTemplates has_and_belongs_to_many DeviceTypes (think: these device types are supported in this activity). The 5th model is our FamilyActivity which belongs_to Family and ActivtyTemplate.
What I am trying to do is get the list of familyActivityInstance.available_devices that are available. Or, stated another way, we know what DeviceTypes are capable of being used in a FamilyActivity based on the Family.devices->DeviceType association, AND, we know the activity supports only certain device types through its FamilyActivity.activity_template->DeviceType association, so we want to deliver a list of the subset of Family.devices that are included in BOTH device type association lists.
Ideally, we'd like to call FamilyActivity.available_devices to get that list. We can brute force this by iterating through the devices and comparing device types, but surely there is a better way!
Here are the models just for reference:
class Family < ActiveRecord::Base
has_many :devices
end
class Device < ActiveRecord::Base
belongs_to :device_type
belongs_to :family
end
class DeviceType < ActiveRecord::Base
has_and_belongs_to_many :family_activities
end
class FamilyActivity < ActiveRecord::Base
belongs_to :family
belongs_to :activity_template
end
class ActivityTemplate < ActiveRecord::Base
has_and_belongs_to_many :device_types
has_many :family_activities, dependent: :nullify
end
In addition to your existing associations:
class DeviceType < ActiveRecord::Base
has_many :devices
end
class FamilyActivity < ActiveRecord::Base
delegate :device_types, to: :activity_template
def available_devices
device_ids = \
device_types.
joins(:devices).
where(devices: {family_id: self.family_id}).
pluck("DISTINCT devices.id")
Device.where(id: device_ids)
end
end

Rails: accessing associated models with several degrees of separation

I am a beginner in rails, and I have a question about accessing one model from another model that is associated with several degrees of separation.
Let's say I have these models:
Account has_many Spies
Spy has many SpyRelationships and belongs to Account
SpyRelationship belongs to Listing and belongs to Spy
How would I set up the associations so that I could simply pull all the listings associated with a given Account (via its spies and spyrelationships)? What line of code would allow me to do so, after those associations are setup properly?
I'm guessing you want to access a listing through a spy?
class Account < ActiveRecord::Base
has_many :spies
has_many :listings, through: :spies
end
class Spy < ActiveRecord::Base
belongs_to :account
has_many :spy_relationships
has_many :listings, through: :spy_relationships
end
class SpyRelationship < ActiveRecord::Base
belongs_to :listing
belongs_to :spy
end
class Listing < ActiveRecord::Base
has_many :spy_relationships
end

Resources