2

3 番目の更新: わかりました、今、私は非常に近いと思います。現在、データを作成しており、パラメーターは DB に設定されています。ビジネスコントローラーの強力なパラメーターを次のように変更しました。

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

既存のビジネスを編集すると、何らかの理由で 2 つの住所が作成されます。1 つは空で、もう 1 つはパラメータが設定されています。だから、誰かが最後のプッシュを持っているなら、私は非常に近いと思います:)。

住所モデル

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 %>

これで、2 つのアドレスが作成されます。1 つは空で、もう 1 つはパラメーターが設定されています。ほとんどそこに:)。

4

2 に答える 2

4

私が取り組んでいるRails 4.0 RC1アプリでポリモーフィックな関連付けを機能させるのが非常に困難なため、私はほとんどばかだと何かが教えてくれます。馬鹿なことはさておき、私は Stack Overflow に私が目にした問題を解決するように依頼し、Ruby on Rails の Google Group の質問を再投稿しました。答えは出ていなかったので、この問題は私が自分で効果的に理解した最初のものになります.

それでいいですよね?

とにかく、私の問題は簡単でした。番地/郵送先/請求先住所を企業、顧客、所有者などで共有したいのですが、同じことを行う 3 つの異なるテーブルをコーディングしたくありません。ポリモーフィックな関連付けは、私がそのような関連付けから収集したものから進むべき道のようです。私はこれに関するガイダンスを探し回っており、モデル化するものがあります。

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)

create で no_method エラーが発生し続けました。そのとき、私は上記の記事に集中して、彼が create も使用していないことに気付きました。彼は使用していました:

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 に行って Ryan が何を持っているかを確認します。そして、http://http://railscasts.com/episodes/154-polymorphic-association-revised>彼は、さまざまなモデルにコメントを追加するときに役立つポリモーフィックなものをいくつか持っています。しかし、それは私がここでやりたかったことに直接役立つものではありませんでした。Stack Overflow でよく読んでいます。Github の Rails リポジトリの問題リストを確認しました。Rails の Google グループを読んでください。私が見ているものを実際にレイアウトしたものは何もありませんでした。

主な理由は、Rails 4 の問題を見ていたためです。

Rails 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 g scaffold を使用した場合、これは Rails 4 で scaffold が自然に作成するものです。強力なパラメーターは、R​​ails の以前のバージョンのモデルの attr_accessible を置き換えます。したがって、このモデルはアドレスとアドレス指定可能のポリモーフィック アソシエーションへの単なる参照であり、ビジネスでは has_one :address, as: アドレス指定可能、accepts_nested_attributes_for :address が追加されます。これで問題ありませんが、まだ何も保存されていません。address_params ハッシュを appliction_controller.rb に追加しました。

私は今、自分が愚かであることに気づきました。アドレスの追加はビジネス コントローラで行われており、この params ハッシュは表示されません。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

私が読んだ記事の 1 つに、has_one アソシエーションが :address_attributes を渡すと書かれていたので、そこに記載しました。今は状況が異なります。データはまだ保存されていませんが、許可されていないエラーは発生していません。そして、ヘルプサイトにはまだ答えがありません。

new、edit、create、および update メソッドを微調整することにしました。

新規および編集では、次のものがありました。

@business.build_address

新規および編集でそれを変更し、以下を作成および更新するために追加しました。

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

これでデータが保存されました。すべてのフィールドがDBに入っていました。問題は2つです。1 つは空で、1 つは新しく更新されるたびに完了していました。そのため、ビジネス コントローラーの create メソッドと update メソッドから上記のコードを削除します。これで、1 つのアドレスが作成されました。正しく。気分が良くなり、ビジネスを開いて住所を編集すると、空白の住所フォームが表示されます。フォーム ビューには何も返されません。

そこで、ビジネス コントローラーの edit メソッドを次のように変更します。

@business.address ||= @business.build_address(params[:address])

これは基本的に、@business.address がある場合は表示し、そうでない場合は @business.address が構築されることを示しています。

今、私は転がっています。フォームを編集すると、保存された住所が表示されるようになりました。アドレスを編集します。編集が保存され、再び表示されます。ただし、これに関連付けられた OLD アドレスは残ります。addressable_id は単純に nil に変更され、新しいアドレス レコードが書き込まれます。それは私が望むものではありません。ヘルプサイトからのヘルプはまだありません。ログには何もありません。

ここでは update メソッドを使用する必要があると思います。そこで、ビジネス コントローラーの update メソッドに次の行を追加します。

@business.address.update(params[:address])

動作の変更はありませんが、ログに許可されていない新しいパラメーターが表示されるようになりました。

「ID」が許可されていないと表示されます。そこで、ビジネス コントローラーの params ハッシュを次のように変更します。

# 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

そしてその上で、物事はうまくいきます。住所でビジネスを作成できます。実際、アドレスを何も入力しなくても、アドレスが作成されます (この時点では検証は行われません)。その住所を完全または空に更新すると、既存のレコードが更新されます。できます。これが最善または最もクリーンな方法であるかどうかはわかりませんが、探し続けます。

ビジネスに関連付けられた作成済みの住所を手動で削除してから、そのビジネスを編集しようとすると、更新するレコードがないため、上記で追加した update メソッドがエラーをスローするという問題が 1 つあります。多分それがなくても生きていける。すべてのビジネス (および最終的にはユーザー、所有者、顧客など) のレコードが空であっても作成し、直接ではなく関連付けを介してのみ削除を許可しても問題ないと思います。

しかし、コードを微調整して、完全な住所を作成し、空にしないようにする方法を見つけることができます。

いずれにせよ、現時点では物事はうまくいっています。

改善できる点や変更すべき点があればお聞きしたいです。

とりあえず、次に​​移ります。

于 2013-05-17T17:48:45.657 に答える
1

コントローラーでは、モデル間の関係を構築する必要があるため、次の代わりに:

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

試す

 @business = @owner.businesses.build(business_params)
于 2013-05-14T21:34:49.370 に答える