2011-10-07 46 views
1

我正在通過RailsTutorial,但爲我在教的中學(調整給定的Twitter克隆)製作一個「通知」webapp。提高我的數據拉爲一個簡單的「公告」軌應用程序

當用戶創建公告時,他們使用複選框確定應顯示哪些等級(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值轉換爲布爾標誌以從模型中拉出公告。

我正在寫的代碼正在工作,但令人難以置信的笨重。請幫助我做出更優雅的東西!如果你有更好的主意,我不會被綁定到這個數據庫模型。 (事實上​​,我真的不喜歡這個數據庫模型,因爲我在許多地方對數據進行了硬編碼)。

# 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

正確的方法來設置此類型的關係了。將經由的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演示瞭如何使用嵌套表單元素通過單個窗體管理多個模型,這將幫助您在將更改應用到模型後保持外觀和感覺相同。我希望這可以幫助,讓我知道如果你需要更多的幫助,這將是一個工作,但最終值得。

+0

謝謝,克里斯!不幸的是,我缺乏足夠的業力來投票給你,但這正是我所期待的(「鐵軌方式」和我的哈克拉方式)。 – 2arrs2ells

+0

沒問題丹尼爾,如果你還有其他問題,請隨時與我聯繫。你可以接受答案,你會得到一個徽章,這是在投票箭頭 –

+0

嗨克里斯 - 再次感謝您的幫助。您是否有任何建議將此設置爲has_and_belongs_to_many關係,並放棄annoucement_grades表?我沒有看到自己在announcement_grades上做了很多事情(連接除外)。 – 2arrs2ells

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}) 
+0

這也非常有幫助!我將與Chris的想法一起運行(因爲我認爲我會從重構中學到很多東西),但我更喜歡你更優雅的黑客。 「where('1 = 1')是一個有趣的黑客 - 這是編寫SQL/db代碼時常見的事情嗎? – 2arrs2ells

+0

這不是一無所知,在這種情況下,但是如果你將這視爲一個學習的機會,那麼我強烈建議你按照克里斯的建議去做,並以「正確」的方式來做 – bioneuralnet

+0

事實上,你總是必須權衡建築決策通過資源限制,這樣做本身並不是錯的,只是不夠靈活和容易實現 –

相關問題