为简单的“公告”rails应用程序改进我的数据拉动

时间:2011-10-07 17:49:41

标签: ruby-on-rails

我正在研究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。当他们登录时,他们的主页应该只显示grade_8 = TRUE的公告。

示例:校长的成绩= 0.当他们登录时,他们的主页应显示所有公告。

我正在努力解决如何将整数user.grade值转换为布尔标志以从模型中提取公告。

我写的代码正在运行,但令人难以置信的笨重。请帮我做一些更优雅的东西!如果你有更好的想法,我不会受这个数据库模型的束缚。 (事实上​​,我真的不喜欢这个db模型,因为我在很多位置都硬编码了等级数。)

# 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 个答案:

答案 0 :(得分:2)

设置此类关系的正确方法是通过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 :(得分:1)

克里斯的榜样在理论上是优越的。但是,您的原始架构可能更实用如果 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})