2013-05-14 46 views
2

第三次更新:好了,現在我很接近,我想。我現在正在創建數據並且正在DB中設置參數。我改變了商業控制器強PARAMS是:軌道4 RC1的多態關聯無法創建

def business_params 
     params.require(:business).permit(:name, :description, :address_attributes=>[:line1, :line2, :city, :state, :zip]) 

當我編輯現有的業務,我得到某種原因產生兩個地址。一個是空的,一個是完整的參數。所以,如果任何人有最後的推動,我認爲我非常接近:)。

地址模型

class Address < ActiveRecord::Base 
belongs_to :addressable, polymorphic: true 
end 

經營模式:

class Business < ActiveRecord::Base 

    #each business belongs to user, through user_id 
     belongs_to :owner 
     has_one :address, as: :addressable 
     accepts_nested_attributes_for :address 

     # each business has many customers and has many services 
     has_many :customers 
     has_many :services 

    validates :owner_id, presence:true 
    validates_presence_of :name 
    #validates_length_of :state, is: 2 

end 

業務控制器:

class BusinessesController < ApplicationController 
    before_action :get_owner 
    before_action :set_business, only: [:show, :edit, :update, :destroy] 
    #helper_method :sort_column, :sort_direction 


    def index 
    @businesses = @owner.businesses 
    end 

    def show 
    #@customer = @business.customers.order(sort_column + " " + sort_direction) 
    end 

    def new 
    @owner = Owner.find(params[:owner_id]) 
    @business = @owner.businesses.build 
    @address = @business.build_address(params[:address]) 

    end 

    def edit 
    @address = @business.build_address(params[:address]) 
    end 

    def create 
    @business = @owner.businesses.new(business_params) 
    @address = @business.create_address(params[:address]) 

    respond_to do |format| 
     if @business.save 
     format.html { redirect_to owner_businesses_url(@owner), notice: 'Business was successfully created.' } 
     format.json { render action: 'show', status: :created, location: @business } 
     else 
     format.html { render action: 'new' } 
     format.json { render json: @business.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    def update 
    @address = @business.create_address(params[:address]) 
    respond_to do |format| 
     if @business.update(business_params) 
     format.html { redirect_to owner_businesses_url(@owner), notice: 'Business was successfully updated.' } 
     format.json { head :no_content } 
     else 
     format.html { render action: 'edit' } 
     format.json { render json: @business.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    def destroy 
    @business.destroy 
    respond_to do |format| 
     format.html { redirect_to owner_businesses_url(@owner) } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_business 
     @business = @owner.businesses.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def business_params 
     params.require(:business).permit(:name, :description, :address_attributes=>[:line1, :line2, :city, :state, :zip]) 
    end 

    def get_owner 
     @owner = Owner.find(params[:owner_id]) 
    end 

    #def sort_column 
    # Customer.column_names.include?(params[:sort]) ? params[:sort] : "first_name"  
    #end 

    #def sort_direction 
    # %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc" 
    #end 
    end 

表單視圖:

 <%= form_for([@owner, @business]) do |f| %> 
     <% if @business.errors.any? %> 
     <div id="error_explanation"> 
      <h2><%= pluralize(@business.errors.count, "error") %> prohibited this business from being saved:</h2> 

     <ul> 
     <% @business.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :name %><br /> 
    <%= f.text_field :name %> 
    </div> 
    <div class="field"> 
    <%= f.label :description %><br /> 
    <%= f.text_area :description %> 
    </div> 

    <%= f.fields_for :address do |address| %> 
    <%= p address.object %> 
    <div class="field"> 
    <%= address.label :line1 %><br> 
    <%= address.text_field :line1 %> 
    </div> 
    <div class="field"> 
    <%= address.label :line2 %><br> 
    <%= address.text_field :line2 %> 
    </div> 
    <div class="field"> 
    <%= address.label :city %><br> 
    <%= address.text_field :city %> 
    </div> 
    <div class="field"> 
    <%= address.label :state %><br> 
    <%= address.text_field :state %> 
    </div> 
    <div class="field"> 
    <%= address.label :zip %><br> 
    <%= address.number_field :zip %> 
    </div> 

    <% end %> 

    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

現在我越來越創建兩個地址。一個是空的,一個是參數集。差不多了 :)。

回答

1

在你的控制器,你需要建立模型之間的關係,所以不是:

@business = @owner.businesses.new(business_params) 

嘗試

@business = @owner.businesses.build(business_params) 
+0

謝謝道奇。這是錯誤的地方,但你指出的具體行已經工作。什麼是不工作的地址部分。 @ business.build_address(params [:address])我認爲是必要的。我現在有一個不允許的參數消息,與以前不同。 @ business.address.create方法用於has_many關係。 – Art

+0

所以,我做了更多的改變,接近。我現在得到了所有地址字段的不允許的參數。我在Rails 4.0中使用強參數,將「address_attributes => {}作爲business_params的一部分,我看到散列已經通過並輸入,但由於沒有能力使用這些屬性而被拒絕。將address_params從私有方法中移出,但我認爲它並沒有出現,所以我必須將它移動到某個幫助器上。 – Art

+0

您是否有attr_accessible:需要訪問這些屬性的模型中添加了address_attributes? – dodgerogers747

4

東西告訴我,我大都具有這樣的困難越來越多態白癡協會在我正在工作的Rails 4.0 RC1應用程序中工作。作爲一個白癡之外,我曾問堆棧溢出來幫助我所看到的問題,轉貼on Rails的谷歌集團的問題紅寶石。沒有答案即將出現,所以,這個問題成爲我自己有效想出的第一個問題。

所以這是很好的,對不對?

不管怎樣,我的問題很簡單。我希望街道/郵寄/帳單地址能夠在企業,客戶,所有者等之間共享。我不想爲三個不同的表格做相同的編碼。一個多態關聯似乎是我從這些關聯中得到的結果。我在這裏尋找指導,並確實有一些事情要模擬。

http://kconrails.com/2010/10/19/common-addresses-using-polymorphism-and-nested-attributes-in-rails/>這個網站很有用,雖然過時了。我使用的是Rails 4,我相信這是寫在Rails 2的尾部。這也幫助我縮小我的時間,因爲我從來沒有做過HAS_ONE協會和我最初的問題是Rails的控制檯,我不能這樣做:

b = Owner.first.businesses.first 
b.address.create!(params n' stuff) 

我一直得到了創建no_method錯誤。那時我真的專注於上面的文章,並意識到他沒有使用創建。他正在使用:

b = Owner.first.businesses.first 
b.build_address(params n' stuff) -- he actually wrote @customer.build_address 

build_association是has_one的東西。我現在很清楚這一點。當然,我可以提前閱讀文檔,但是,在此期間我閱讀了它們。如果您有興趣,可以在http://guides.rubyonrails.org/association_basics.html#has_one-association-reference上有效閱讀。

我按照那個文件非常密切,但它不是很正確。我業務控制器DID的新方法中的「build_address」項允許我的表單中的fields_for顯示。但是,沒有任何東西正在寫入數據庫。一個空的記錄正在被放入具有所有零值的地址,並且完全不附加到被添加的業務。顯然,如果一個企業實際上被「編輯」而不是創建新的,你根本沒有看到任何地址表單,所以我想我們至少需要編輯字段中的build_address方法。

我在那是正確的,但仍然沒有保存。

和往常一樣,我會去Railscasts看看瑞恩有什麼。而且,當他爲不同的模型添加註釋時,他有一些多態的東西,這將是很棒的。但這對我想在這裏做的事情沒有直接的益處。我在Stack Overflow上讀了很多。在Github的Rails存儲庫中檢查問題列表。閱讀Rails Google小組。沒有真正展示我所看到的。

很大程度上是因爲我看到了Rails 4問題。

強參數內置於滑軌4。所以我增加了以下的地址控制器考慮到這一點:

# Never trust parameters from the scary internet, only allow the white list through. 
def address_params 
    params.require(:address).permit(:line1, :line2, :city, :state, :zip) 
end 

這是支架將使你自然Rails中4,如果你使用爲此的鐵軌g腳手架。強大的參數替代了以前版本Rails的模型中的attr_accessible。因此,該模型僅僅是對地址和可尋址業務的多態關聯的引用,並添加了has_one:address,如:addressable以及accepts_nested_attributes_for:address。這一切都很好,但仍然沒有得到保存。我甚至將address_params散列添加到appliction_controller.rb。

我意識到現在我很愚蠢。地址的添加發生在業務控制器中,永遠不會看到這個參數散列。即使在application_controller.rb中也沒有任何改變。所以不可能是這樣。

我看到在日誌中傳遞的參數,並試圖插入,但一個不允許的參數「地址」的參數不斷顯示。

我在這裏尋求幫助,並試圖調整它。

我看到https://github.com/rails/strong_parameters#nested-parameters>這個部分在強大的參數庫中的github上。我不明白爲什麼accepts_nested_attributes_for不會爲我做這件事,但我進入商業控制器和調整params哈希表有看起來像這樣:

# Never trust parameters from the scary internet, only allow the white list through. 
def business_params 
    params.require(:business).permit(:name, :description, :address_attributes => [:line1, :line2, :city, :state, :zip]) 
end 

一個我讀到的文章說,HAS_ONE協會通過:address_attributes通過,所以我把它放在那裏。現在情況不同了。數據仍未保存,但我沒有收到任何未經許可的錯誤。在幫助網站上仍然沒有答案。

我決定調整我的新建,編輯,創建和更新方法。

在新建和編輯我:

@business.build_address 

我改變,在新的和編輯,並加入到創建和更新如下:

@business.build_address(params[:address]) -- NOTE, :address_attributes also appears to work there. 

現在數據保存。所有的字段都進入了數據庫。問題是兩個人。其中一個是空的,一個在每個新的和每個更新中都完成。所以,我從業務控制器中的創建和更新方法中刪除上面的代碼。現在我創建了一個地址。正確。感覺良好的我自己,我打開業務編輯地址,我得到一個空白的地址表。沒有任何東西被傳回窗體視圖。

於是,我改變了業務控制我的編輯方法是這樣的:

@ business.address || = @ business.build_address(PARAMS [:地址])

這基本上說,如果有一個@ business.address,顯示它,否則@ business.address將被建立。

現在我在滾動。當我編輯表單時,我現在可以看到保存的地址。我編輯地址。編輯被保存並再次顯示。但與此相關的舊地址仍然存在。 addressable_id被簡單地改變爲零,並且寫入新的地址記錄。這不是我想要的。仍然沒有幫助來自幫助網站。根本沒有任何記錄。

我覺得自己的更新方法應該是用在這裏。所以我下面的行添加到業務控制器的更新方法:

@ business.address.update(PARAMS [:地址])

沒有行爲的改變,但現在的日誌現在顯示了一個新的未經許可的參數。

它顯示「ID」未被許可。所以,我改變我的業務控制器參數哈希讀取:

# Never trust parameters from the scary internet, only allow the white list through. 
def address_params 
    params.require(:address).permit(:id, :line1, :line2, :city, :state, :zip) 
end 

而在這一點上,事情的工作。我可以創建一個地址的業務。事實上,即使我沒有填寫地址的任何內容,地址也會被創建(此時沒有任何驗證)。我可以更新該地址,填寫或清空,並更新現有記錄。有用。我不確定這是最好還是最乾淨的方式,但我會繼續尋找。

一個問題存在,如果我手動刪除與業務相關的創建的地址,然後嘗試編輯業務,我在上面添加的更新方法拋出給沒有要更新的記錄錯誤。我大概可以沒有這種生活。我想我可以爲每個企業(最終用戶,所有者,客戶等)創建一個記錄,即使它是空的,然後只允許通過關聯刪除而不是直接刪除。

但我可以調整代碼只找到一個方法來創建一個完整的地址,而不是把它寫空。

在任何情況下,這類事情在目前的工作。

我很願意聽到的話,有什麼事我可以提高或應該改變。

現在,我移動到下一個事情。

+0

很好的答案!我遇到了與多態has_one關聯有關的另一個問題:InverseOfAssociationNotFoundError。我會嘗試使用您的解決方案,但我幾乎相信它不會對我的問題產生影響。 :S我的代碼看起來就像你的。<你有什麼想法? – JustBasti