Улучшите мои данные для простого приложения "анонсы" rails - PullRequest
1 голос
/ 07 октября 2011

Я работаю через RailsTutorial , но создаю веб-приложение "Объявления" для средней школы, в котором я преподаю (настройка данного клона Twitter).

Когда пользователи создают объявление, они используют флажки, чтобы определить, каким оценкам оно должно отображаться (1-3 оценки могут быть истинными). Это работает правильно, я храню оценки как булевы.

create_table "announcements", :force => true do |t|
t.string   "content"
t.integer  "user_id"
t.boolean  "grade_6"
t.boolean  "grade_7"
t.boolean  "grade_8"
t.date     "start_date"
t.date     "end_date"
t.datetime "created_at"
t.datetime "updated_at"

конец

У моих пользователей также есть поле оценки, которое является целым числом. Я хочу использовать это, чтобы домашняя страница каждого пользователя показывала объявления для его оценки.

Пример: учитель 8-го класса имеет оценку = 8. Когда они входят в систему, на их домашней странице должны отображаться только объявления, у которых оценка_8 = ИСТИНА.

Пример: участник имеет оценку = 0. Когда они входят в систему, на их домашней странице должны отображаться все объявления.

Я борюсь с тем, как преобразовать целочисленное значение user.grade в логические флаги для извлечения объявлений из модели.

Код, который я пишу, работает, но невероятно неуклюж. Пожалуйста, помогите мне сделать что-то более элегантное! Я не привязан к этой модели БД, если у вас есть идея получше. (На самом деле, мне действительно не нравится эта модель БД, поскольку я жестко задаю количество оценок в нескольких местах).

# Code to pull announcements for the home page
def feed
case grade
when 6
  grade_6
...
else
  grade_all
end 
end

# Example function to pull announcements for a grade
def grade_6
  Announcement.where("grade_6 = ? AND start_date >= ? AND end_date <= ?", 
                     TRUE, Date.current, Date.current)

Ответы [ 2 ]

2 голосов
/ 07 октября 2011

правильный способ установить этот тип отношений - использовать отношение «многие ко многим» через has_many:

class Announcement < ActiveRecord::Base
  has_many :announcement_grades
  has_many :grades, :through => :announcement_grades
end

class AnnouncementGrades < ActiveRecord::Base
  belongs_to :grade
  belongs_to :announcement
end

class Grade < ActiveRecord::Base
  has_many :announcement_grades
  has_many :announcements, :through => :announcement_grades
end

тогда ваши миграции будут:

create_table :announcements, :force => true do |t|
 t.date :start_date
 t.date :end_date
 t.timestamps #handy function to get created_at/updated_at
end
create_table :announcement_grades, :force => true do |t|
 t.integer :grade_id
 t.integer :announcement_id
 t.timestamps
 #start and end date might be more appropriate here so that you can control when to start and stop a particular announcement by grade rather than the whole announcement globally, depending on your needs.
end
create_table :grades, :force => true do |t|
  t.timestamps
  #now you have a bona-fide grade object, so you can store other attributes of the grade or create a relationship to teachers, or something like that
end

Итак, теперь вы можете просто найти свою оценку, а затем вызвать объявления для фильтрации:

@grade = Grade.find(params[:id])
@announcements = @grade.announcements

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

1 голос
/ 07 октября 2011

Пример Криса теоретически превосходен. Тем не менее, ваша оригинальная схема может быть более практичной , если 1) вы знаете, что ваше приложение не станет более сложным, и 2) американская система K-12 готова остаться (я бы сделал ставку на это .. .). Если вы предпочитаете придерживаться схемы, которая у вас уже есть, вот некоторые улучшения, которые вы можете внести в код:

Давайте добавим область оценки для вашей модели объявления

class Announcement < ActiveRecord::Base
  ....
  scope :grade, lambda do |num|
    num > 0 ? where("grade_#{num} = ?", true) : where('1=1')
  end
  ....
end

Это позволило бы значительно упростить кодирование, например

teacher = User.find(user_id)
announcements = Announcement.grade(teacher.grade).where('start_date >= :today AND end_date <= :today', {:today => Date.today})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...