#ruby #haml #datamapper #erb
#ruby #haml #datamapper #ошибка
Вопрос:
У меня есть устаревшая база данных, которая находится за действительно дерьмовым PHP-приложением. Веб-приложение вызывает всевозможные проблемы с базой данных, и мне просто нужен быстрый способ представления того, что хранится в базе данных, таким образом, чтобы мой клиент мог видеть, насколько серьезна проблема, поэтому я создал приложение Sinatra DataMapper, но у меня возникли проблемы с вычислением некоторых значений в представлении.
В конце концов, я хочу таблицу, подобную этой:
Profile Registration Signup Payment
Payment
Signup Payment
Registration Signup Payment
Signup <- Signup w/ no payments
Profile Registration Signup Payment
Registration <- Registration w/ no Signups
Profile <- Profile w/ no Registrations
Моя первая проблема заключается в том, что для этого требуется тонна SQL-запросов [в основном (n 1) * (n 1) * (n 1) * (n 1)], но AFAIK нет способа заставить DataMapper выполнять быструю загрузку вложенных моделей или, в любом случае, кэшировать модель данных таким образом, чтобы чтение было более эффективным. (Я ничего не записываю обратно в БД, и снимок базы данных в порядке — на самом деле меня не волнуют текущие обновления). Пока это допустимо, потому что это одноразовый отчет.
Моя вторая проблема заключается в вычислении диапазона строк для заданных столбцов. Сначала я просто использовал количество платежей для текущей области ( profile.registrations.signups.payments.size
, registration.signups.payments.size
и т.д.), Но, как вы можете видеть в первом примере выше, на самом деле на один платеж меньше, чем потребовалось бы для получения точного диапазона строк для профиля.
Единственное теоретическое решение, которое я смог придумать, — это в основном перебирать каждый дочерний объект на каждом шаге по пути, чтобы точно выяснить, какие дочерние объекты доступны после этого шага, но это кажется действительно неэлегантным и потребовало бы экспоненциального увеличения выполняемого SQL.
Есть ли какой-либо другой способ, которым я могу подойти к этому? Я не женат на DataMapper или HAML, я просто хочу сделать это как можно эффективнее.
Я вставляю свой текущий HAML и модели данных ниже для справки.
index.haml (это неприятно, я знаю)
#content
%p #{@profiles.size} Profiles
%table.display{:border=>1, :cellpadding=>2,:width=>'100%'}
%thead
%th Prof ID
%th Profile
%th Reg's
%th Reg ID
%th Registration
%th Signups
%th Event ID
%th Event
%th Event Date
%th Payments
%th Pmt ID
%th Amt
%th Pmt Date
%tbody
- @profiles.each do |profile|
- profile_rowspan = [profile.registrations.signups.payments.size, profile.registrations.signups.size, profile.registrations.size, 1].detect { |i| i > 0 }
%tr{:valign=>'top'}
%td{:rowspan => profile_rowspan, :class => "profile"} #{profile.id}
%td{:rowspan => profile_rowspan} #{profile.firstname} #{profile.lastname}
%td{:rowspan => profile_rowspan} #{profile.registrations.size}
- if profile.registrations.size == 0
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
%td{:rowspan => profile_rowspan}
- profile.registrations.each_with_index do |registration, reg_index|
- if reg_index != 0
!= "</tr><tr valign="top">"
- reg_rowspan = [registration.signups.payments.size, registration.signups.size, 1].detect { |i| i > 0 }
%td{:rowspan => reg_rowspan, :class => "registration"} #{registration.id}
%td{:rowspan => reg_rowspan} #{registration.firstname} #{registration.lastname}
%td{:rowspan => reg_rowspan} #{registration.signups.size}
- if registration.signups.size == 0
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
%td{:rowspan => reg_rowspan}
- registration.signups.each_with_index do |signup, signup_index|
- if signup_index != 0
!= "</tr><tr valign="top">"
- signup_rowspan = [signup.payments.size, 1].detect { |i| i > 0 }
%td{:rowspan => signup_rowspan, :class => "signup"} #{signup.event.id}
%td{:rowspan => signup_rowspan} #{signup.event.event_title}
%td{:rowspan => signup_rowspan} #{signup.event.event_start}
%td{:rowspan => signup_rowspan} #{signup.payments.size}
- if signup.payments.size == 0
%td{:rowspan => signup_rowspan}
%td{:rowspan => signup_rowspan}
%td{:rowspan => signup_rowspan}
- signup.payments.each_with_index do |payment, payment_index|
- if payment_index != 0
!= "</tr><tr valign="top">"
%td{:class => "payment"} #{payment.id}
%td #{payment.total}
%td #{payment.payment_date}
profile.rb
class Profile
has n, :registrations
end
registration.rb
class Registration
belongs_to :profile
has n, :signups
has n, :payments
end
регистрация.rb
class Signup
belongs_to :registration
belongs_to :event
has n, :payments
end
payment.rb
class Payment
belongs_to :registration
belongs_to :signup
end
event.rb
class Event
has n, :signups
has n, :payments, :through => :signups
end
Ответ №1:
Если вы используете MySQL, он может возвращать результаты запроса в формате HTML. Стоило бы посмотреть, что он может сделать в качестве отправной точки.
Затем вы могли бы использовать Nokogiri для поиска пустых ячеек и манипулирования HTML-кодом по своему усмотрению.