2014-10-29 3 views
1

У меня есть три таблицы Бизнес, Пользователи и Подписки. Цель состоит в том, чтобы иметь возможность получать имена компаний, связанные с пользователем. Результат должен быть массив имен бизнеса, которые пользователь подписался на в подпискахИспользование реляционной базы данных

Список таблиц

Schema |  Name  | Type | 
--------+-------------------+------- 
public | businesses  | table 
public | subscriptions  | table 
public | users    | table 

предприятия Таблица

Column |   Type               
------------+----------------------------- 
id   | integer      
name  | character varying(255)  
created_at | timestamp without time zone 
updated_at | timestamp without time zone 

Бизнес-модель

class Business < ActiveRecord::Base 

end 

Подписки Таблица

Column |   Type         
-------------+----------------------------- 
id   | integer      
user_id  | integer      
business_id | integer      
created_at | timestamp without time zone 
updated_at | timestamp without time zone 

Подписка Модель

class Subscription < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :business 
end 

Пользователи Таблица

 Column  |   Type         
-----------------+----------------------------- 
id    | integer     
username  | character varying(255)  
password_digest | character varying(255)  
email   | character varying(255)  
created_at  | timestamp without time zone 
updated_at  | timestamp without time zone 

пользователя Модель

class User < ActiveRecord::Base 
     has_secure_password 
     has_many :subscriptions 
    end 

Rails консоль

u = User.find(1) 
u.subscriptions.businesses.name 

Response: undefined method `business' 

ответ

1

Вместо того чтобы делать дополнительный запрос для каждой подписки (как в ответ Алирезой в), вы можете сделать это с помощью одного запроса с использованием Rails' встроенный includes метод:

subscriptions = u.subscriptions.includes(:business) 

Это вернет отношение для всех Подписок, включая их связанные предприятия. Теперь вы можете получить имена бизнес, не делая дополнительный запрос:

business_names = subscriptions.map {|sub| sub.business.name } 

Я думать вы также можете сделать это за один шаг с помощью pluck:

business_names = u.subscriptions.includes(:business).pluck("businesses.name") 

Я не уверен pluck пьесы хорошо с includes, но стоит попробовать.

+0

Я получил эту ошибку. Ассоциация с именем ' подписки ' не была найдена в Подписке; возможно, вы это написали? – user3882976

+0

@ user3882976 Извините, я думаю, что это должно быть 'include (: business)' вместо 'includes (: subscriptions =>: business)'. Я обновил свой ответ. –

1

поскольку пользователь имеет много подписок, вызов u.subscriptions возвращает массив подписок, поэтому вам нужно перебрать массив и вызвать business ассоциации по каждой записи. вы можете добиться того, что вам нужно с помощью:

business_names = u.subscriptions.map {|subscription| subscription.business.name } 
+0

За исключением того, что будет выполняться один запрос для каждой подписки - если есть 100 подписчиков, вы получите 100+ запросов. Не очень хорошее решение. –

+0

@ Иордан. Это только ответы на вопрос, о которых спрашивал ОП, конечно, его можно оптимизировать по-разному, но это не то, о чем спрашивает ОП. Я мог бы опубликовать 10 способов добиться того же, используя 'joins' и' includes'. – Alireza

+0

Я не сказал, что это был неправильный ответ, я сказал, что это не отличный ответ.Если вы «можете опубликовать 10 способов достижения одного и того же», тогда мне непонятно, почему вы выбрали одно из худших. –

Смежные вопросы