расширенный (nexted) has_many: через запросы в Ruby on Rails (double-JOIN) - PullRequest
2 голосов
/ 29 апреля 2011

У меня слишком многослойная структура базы данных, однако мне она, похоже, нужна.То есть каждый из посетителей нашего веб-сайта может иметь одну учетную запись с поддержкой нескольких пользователей (например, идентификаторов).Теперь они могут создавать заявки, сгруппированные по разделам заявки, и у нас есть менеджер билетов (оператор) для обработки входящих заявок.Не каждый менеджер билетов может видеть каждый билет, но только те, для которых этот менеджер является участником данного раздела заявки.

Теперь я полностью справляюсь с запросами через необработанные операторы SQL, но мне не удалось выразить словами эти два специальныхзапрашивает путь Rails.

Вот (абстрактная) модель:

# account system
class Account < ActiveRecord::Base
  has_many :users
  has_many :tickets, :through => :users
  has_many :managing_ticket_sections, ... # TicketSection-collection this account (any of its users) is operate for
  has_many :managing_tickets, ...         # Ticket-collection this account (any of its users) may operate on
end

class User < ActiveRecord::Base
  belongs_to :account
  has_many :tickets
  has_many :managing_ticket_sections, ... # TicketSection-collection this user is operate for
  has_many :managing_tickets, ...         # Ticket-collection this user may operate on
end

# ticket system
class Ticket < ActiveRecord::Base
  belongs_to :author, :class_name => "User"
  belongs_to :assignee, :class_name => "User"
  belongs_to :section, :class_name => "TicketSection"
end

class TicketSection < ActiveRecord::Base
  has_many :tickets
  has_many :operators
end

class TicketSectionManager < ActiveRecord::Base
  belongs_to :manager, :class_name => "User"
  belongs_to :section
end

Мне известны базовые has_many :through -конструкты, однако здесь я обращаюсь к более чем трем таблицамчтобы получить билеты.

Что-то, на самом деле работает в модели пользователя:

class User < ActiveRecord::Base
  has_many :managing_relations, :class_name => "TicketSectionManager" # XXX some kind of helper, for the two below
  has_many :managing_sections, :class_name => "TicketSection", :through => :managing_relations, :source => :section
  has_many :managing_tickets, :class_name => "Ticket", :through => :managing_relations, :source => :section
end

Здесь я использую вспомогательное отношение (managing_relations), которое абсолютно никогда не используется, кромедвумя отношениями has_many ниже.Я не смог описать отношение User.managing_sections или User.managing_tickets без этого помощника, где мне нужен совет.

Во-вторых, клиент должен посмотреть все билеты, которые онможет управлять любым пользователем (представьте себе личность), в который он вошел, так что мне нужен способ собрать все билеты (/ разделы), которыми может управлять эта учетная запись (идентифицированная как членсоответствующего TicketSection)

Здесь я даже не смог выразить это отношение рубиновым способом, и мне пришлось обходить его следующим образом:

class Account
  def managing_tickets
    Ticket.find_by_sql("SELECT t.* FROM tickets AS t
        INNER JOIN ticket_section_managers AS m ON m.section_id = t.section_id
        INNER JOIN users AS u ON u.id = m.user_id
        WHERE u.account_id = #{id}")
  end
end

Буду признателен за любыедобрые советы и большое спасибо заранее, Кристиан Парпарт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...