2012-03-09 52 views
1

我覺得我不知道我在做什麼..我有一個模糊的想法。我希望到目前爲止我做到了這一點。我是否正確使用導軌形式?

任何你可以看到重構這種方式將不勝感激。

我注意到它的一個錯誤是它不會加載之前提交的正確選項,如果出現錯誤並且它發佈到相同的URL。文本輸入似乎加載了以前的值,但選擇和單選按鈕重置爲每次提交時的默認值。

ResourcesController#新

def new 
    @resource = Resource.new 
    @title = "Submit Resource" 
    @categories = Category.all 
end 

ResourcesController#創建(請注意,我有@categories = Category.all兩......根據幹林不知道還有什麼地方應該去,或者只能在第一種形式提交。

def create 
    @title = "Submit Resource" 
    @categories = Category.all 

    @resource = Resource.new(params[:resource]) 

    category_ids = @categories.map { |c| c[1] } 

    if @resource.valid? and category_ids.include? params[:category_id] 
     @resource.cost = params[:cost] 
     @resource.category_id = params[:category_id] 
     @resource.save 
     redirect_to root_url 
    else 
     render :action => :new 
    end 
    end 

Resource.rb(模型)

# == Schema Information 
# 
# Table name: resources 
# 
# id   :integer   not null, primary key 
# upvotes  :integer   default(0) 
# downvotes :integer   default(0) 
# url   :string(255) 
# title  :string(255) 
# cost  :integer   default(0) 
# description :text 
# flags  :integer 
# category_id :integer 
# user_id  :integer 
# created_at :datetime  not null 
# updated_at :datetime  not null 
# 

class Resource < ActiveRecord::Base 

    belongs_to :category 
    belongs_to :user 
    has_many :favorites 
    has_many :resource_tags 
    has_many :tags, :through => :resource_tags 

    attr_accessible :url, :title, :cost, :description, :category_id, :user_id 

    # Pseudo-Enum 
    COST = [:free, :paid, :both] 

    url_regex = /^(?:http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}(:[0-9]{1,5})?(\/.*)?$/ix 

    validates :url,   :presence => true, 
          :format => { :with => url_regex, 
             :message => "must be valid"}, 
          :uniqueness => { :case_sensitive => false, 
              :message => "has already been submitted"} 
    validates :title,  :presence => true, 
          :length => { :within => 6..75 } 
    validates :cost,  :presence => true 
    validates :description, :presence => true, 
          :length => { :within => 25..200 } 
    validates :category_id, :presence => true, 
          :format => { :with => /\d+/ } 
    validates :user_id,  :presence => true, 
          :format => { :with => /\d+/ } 

    def cost 
    COST[read_attribute(:cost)] 
    end 

    def cost=(value) 
    write_attribute(:cost, COST.index(value.downcase.to_sym)) 
    end 

    def category_id 
    read_attribute(:category_id).to_i 
    end 

    def category_id=(value) 
    write_attribute(:category_id, value.to_i) 
    end 

end 

我v瀏覽資源#新表格

<div class="field"> 
    <%= f.label :category %> 
    <%= select_tag(:category_id, options_for_select(@categories.map {|c|[c.name, c.id]})) %> 
    </div> 

最後問:我還沒有使用user_id字段呢。這將從設計中拉出,並將用戶與提交的資源相關聯。但是,如何在不進行某種輸入(如隱藏輸入)的情況下分配這些內容。這會在控制器的幕後進行嗎?

回答

1

要你最後一個問題:

色器件增加了CURRENT_USER方法是登錄的用戶。因此,如果用戶有多個資源,你可以這樣做:

@resource = current_user.resources.new(params[:resource]) 

第一個問題:

當形式呈現它是基於@resource & @categories變量這樣做。當您發佈表單時,調用create action會創建一個新的@resource。如果因爲任何原因保存失敗,則使用新的@resource變量重新渲染表單。您遇到的問題是,當您再次顯示錶單時,未設置@ resource.category。所以你必須在is_valid之前做到這一點?檢查。

def create 
    @title = "Submit Resource" 
    @categories = Category.all 

    @resource = Resource.new(params[:resource]) 
    @resource.category = Category.find(params[:category_id]) 

    if @resource.valid? # won't be valid if there is no category found. 
     @resource.cost = params[:cost] 
     @resource.save 
     redirect_to root_url 
    else 
     render :action => :new 
    end 
    end 

但真正的問題在於你的形式。它應該將category_id嵌套在資源參數中,以便在執行Resource.new(params [:resource])時設置類別。

檢查控制檯中的POST請求體或其他東西,看它是否嵌套在資源中。我不知道它的確切語法,但如果你改變這個,你可以刪除@ resource.category = Category.find這一行。

+0

真棒的答案,讓我仔細看看這個,非常感謝 – Tallboy 2012-03-09 19:46:11

1

看起來有問題,創建行動

def create 
    @title = "Submit Resource" 
    @categories = Category.all 

    @resource = Resource.new(params[:resource]) 
    if @categories.collect(&:id).include?(params[:category_id].to_i) 
     @resource.category_id = params[:category_id] 
    end 
    @resource.user = current_user 
    if @resource.valid? 
     @resource.cost = params[:cost] 
     @resource.save 
     redirect_to root_url 
    else 
     render :action => :new 
    end 
end 

視圖

<div class="field"> 
    <%= f.label :category %> 
    <%= select_tag(:category_id, options_for_select(@categories.map {|c|[c.name, c.id]}, :selected => @resource.category_id)) %> 
</div> 
+0

謝謝,看起來好多了(我最初想要做但我不知道有關collect(&:id)。但是...它似乎仍然不會加載以前的表單輸入。 – Tallboy 2012-03-09 19:40:46

1

捎帶上的Sandip,您可以通過使用的before_filter

class ResourcesController < ApplicationController 
    before_filter :load_categories, :only => [:show, :create] 

    def new 
    @resource = Resource.new 
    end 

    def create 
    @resource = Resource.new(params[:resource]) 
    @resource.category = Category.find(params[:category_id]) 

    if @resource.valid? # won't be valid if there is no category found. 
     @resource.cost = params[:cost] 
     @resource.save 
     redirect_to root_url 
    else 
     render :action => :new 
    end 
    end 

    private 

    def load_categories 
    @categories = Category.all 
    end 
end 

,如果你還打算堅持你的應用程序佈局內@title,我會在你的看法改變@title乾涸你的行動:

yield(:title) || 'My Site' 

,並在相應的頁面上使用:

content_for(:title) do 
    Submit Resource 

它會默認爲'我的網站',除非另有規定。