2010-06-29 69 views
1

使用accept_nested_attributes_for時,我遇到需要原件存在的驗證時卡住了。該代碼將有助於澄清這句話。有沒有辦法檢查記錄是否由活動記錄中的另一個模型構建?

class Foo < ActiveRecord::Base 
    has_one :bar 
    accepts_nested_attributes :bar 
end 

class Bar < ActiveRecord::Base 
    #property name: string 
    belongs_to :foo 
    validates_presence_of :foo #trouble line! 
end 

#now when you do 
foo = Foo.create! :bar_attributes => {:name => 'steve'} 
#you get an error because the bar validation failed 

我想編寫雲像一個驗證...

class Bar < ActiveRecord::Base 
    validates_presence_of :foo, :unless => :being_built_by_foo? 
end 

我目前使用rails3.beta4

謝謝

唉我不對這篇文章有一個答案,但我想出了另一種方式,所以我不需要驗證。

因爲bar不應該沒有foo,那麼任何創建沒有foo_id的bar的請求都是錯誤的。在實際的例子中,foo是一個項目,而bar是一個出價。它是一個嵌套的資源,但我希望能夠訪問json應用程序,以便能夠從/ bids位置查詢信息,以便路由器看起來像。

resources :bids 
resources :projects do 
    resources: bids 
end 

,然後我必須確保所有HTML訪問使用project_bids_path或的form_for [:項目,@出價]等,這接下來的部分是基本上未經檢驗,但到目前爲止所期望的行爲是存在的。我從Yehuda的職位的想法上通用的行動http://yehudakatz.com/2009/12/20/generic-actions-in-rails-3/

#I'm sure there is a better way then map.connect 
map.connect "projects/invalid_id", :controller => "projects", :action => "invalid_id" 
resources :projects 
    resources :bids 
end 

#couple of changes from Yehuda 
def redirect(*args, &block) 
    options = args.last.is_a?(Hash) ? args.pop : {} 

    path = args.shift || block 
    path_proc = path.is_a?(Proc) ? path : proc {|params| path % params } 
    status = options[:status] || 301 

    lambda do |env| 
    req = Rack::Request.new(env) 
    #Get both the query paramaters and url paramaters 
    params = env["action_dispatch.request.path_parameters"].merge req.params 
    url = path_proc.call(params.stringify_keys) 
    #Doesn't add the port back in! 
    #url = req.scheme + '://' + req.host + params 
    #content-type might be a bad idea, need to look into what happens for different requests 
    [status, {'Location' => url, 'Content-Type' => env['HTTP_ACCEPT'].split(',').first}, ['Moved Permanently']] 
    end 
end 

def bid_path 
    redirect do |params| 
    if params['project_id'] 
     "/projects/#{params['project_id']}/bids/#{params['id']}" 
    else 
     '/projects/invalid_id' 
    end 
    end 
end 


match "bids", :to => bid_path 
match "bids/:id", :to => bid_path 

然而,做了這一切之後,我最肯定覺得不值得。我認爲nested_attributes會破壞一些東西,如果驗證不起作用,它可以得到改進,但是在仔細查看一段代碼之後,我不確定如何修復它,或者它是否值得。

回答

0

首先,當使用nested_attributes時,您將看到容器的存在。在這個例子中:當你保存Foo並且還有Bar的嵌套表單時,Bar則由Foo構建。

我認爲如果您確定只在Foo的上下文中使用Bar,則不需要進行這種驗證。

順便說一句,儘量寫驗證如下(爲Rails3中新的首選語法):

validates :foo, :presence => true 

希望這有助於 一個。

+0

感謝格式化提示!我遇到的問題來自於嘗試創建一個不錯的界面。該項目還有一個JSon API部分。在現實中,酒吧是一個投標,foo是一個項目。在創建項目時從Web UI中,您可以使用nested_attributes設置出價。項目之後,您可以在使用nested_attributes的項目頁面上編輯出價。在json方面,我希望有人能夠通過在project_id中發佈到出價控制器來創建出價。要做到這一點,我需要驗證project_id是否存在,現在不幸的是,它在控制器中。 – daicoden 2010-07-01 10:34:35

+0

你總是可以做一個很好的解決方法,而不使用僅使用一點JS的基於json的請求。例如,您爲嵌入式表單製作出價,然後使用JS創建鏈接/按鈕以添加新的出價表單(只需點擊即可添加儘可能多的出價)。當您編輯/保存項目時,您會正確保存出價。如果你對這個解決方案感興趣,我可以給你一些示例代碼;-) – 2010-07-01 11:07:15

+0

這是一個好主意!我仍然認爲你應該可以設置驗證! >。但是,我一直在想的例子越來越多。我想我可以爲該項目的另一部分設置JavaScript,但我很欣賞這個提議。特別是對於這個出價問題,我實際上需要使其成爲嵌套資源,因爲沒有項目就不能存在出價。謝謝你的幫助! – daicoden 2010-07-01 13:20:30