9

現在の場所フィールド (都市と国) を持つユーザー エンティティがあります。この情報を保持するために、ユーザー数が多い Location というエンティティを作成しました。

User モデルに「has_one」または「belongs_to」を入れる必要があるかどうかは完全にはわかりませんが、場所の外部キーを持たせたい場合は、「belongs_to」を入れる必要があります。また、ユーザーを編集するときにユーザーの現在の場所を編集できるようにしたいと考えています。そのため、ネストされた属性を使用しています。しかし、ユーザーを編集すると、編集されたユーザーに関連付けることなく、毎回新しい場所を追加することになります。あなたは私を助けることができます?

私のコードは次のとおりです。

#User Model
class User < ActiveRecord::Base
  ## Relationships
  belongs_to :current_location, :class_name => 'Location'
  accepts_nested_attributes_for :current_location
end

#Location Model
class Location < ActiveRecord::Base
  #Relationship
  has_many :users
end

# part of the _form_edit.haml
- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location

#Application Helper
#nested attributes for user and location
def setup_user(user)
  returning(user) do |u|
    u.build_current_location if u.current_location.nil?
  end
end

#in the user controller (added after edit)
def update
    @user = @current_user
    if @user.update_attributes(params[:user])
      flash[:notice] = "Account updated!"
      redirect_to account_url
    else
      render :action => :edit
    end
  end
4

4 に答える 4

10

他の人が指摘しているように、あなたが直面している正確な問題は、コントローラーがロケーションIDを正しく受信していないことです。ロケーションIDが間違ったパラメーターを介して渡されているように見えます。残念ながら、ロケーションIDは新しいレコードに存在しないため、フォームでこれを行うことはできません。

問題は、belongs_to関係でaccepts_nested_attributes_forを使用することに起因します。動作は明確に定義されていません。これは文書化されたバグのようです。したがって、accepts_nested_attributes_forは、関係の1つまたは多くの側面を持っている必要があります。

考えられる解決策は次のとおりです。

  1. Accepted_nested_attributes_forをLocationモデルに移動し、逆にフォームを作成します。

    -form_for @location do |location_form|
     ...
     =location_form.fields_for @user do |user_form|
       ....
    

    残念ながら、これでは情報を論理的に提示することはできません。また、適切なユーザーの編集が困難になります。

  2. 結合モデルを使用して、1つの:through関係を作成します。

    正直なところ、accept_nested_attributes_forが:through関係でどの程度うまく機能するかはわかりませんが、レコードのリンクに関する問題は確実に解決されます。

  3. accepts_nested_attributes_forを無視し、コントローラーで昔ながらの方法で関連付けを処理します。

    実際にはaccepts_nested_attributes_forを保持します。それはいくつかの便利な便利なメソッドを提供しますが、update_attributes/createステートメントに到達させないでください。

    def update 
      @user = @current_user 
      completed = false
      location_params = params[:user].delete(:current_location_attributes)
    
      User.transaction do
        @location = Location.find_or_create_by_id(location_params)
        @user.update_attributes(params[:user]) 
        @user.current_location = @location
        @user.save!
        completed = true
      end
      if completed
        flash[:notice] = "Account updated!" redirect_to account_url 
      else 
        render :action => :edit 
      end
    end
    

のフィールドは、新しい場所を作成していない場合、current_location_attributesハッシュのidフィールドに自動的に入力されます。ただし、find_or_create_by_idを機能させるには、ハッシュに:idエントリが必要です。IDがデータベースにない場合は、正しく自動インクリメントされたIDで作成されます。新しい場所を作成する場合は、それを追加する必要があります。を使用してフォームに追加するのが最も簡単=location_form.hidden_field :id, 0 unless current\_location.new\_record?です。

ただし、重複する場所の作成を減らし、Location.find_or_create_by_id行をLocation.find_or_create_by_locationに変更することをお勧めします。これにより、一意性の検証に失敗した場合のエラーも削減されます。

于 2009-10-20T16:10:35.500 に答える
0

デフォルトでは、テーブルにフィールドがあるbelongs_to :current_location, :class_name => 'Location'ことが期待されます。これを取得すると、次のようなことができるようになります。Userscurrent_location_id

@user = @current_user
@user.update_attributes(params[:user])

@location = @user.current_location or @user.build_current_location
@location.update_attributes(params[:location]) 

@user.current_location.save!
@user.save!
于 2009-10-20T19:17:31.860 に答える
0

ネストされた属性の ID を提供しません。したがって、レールはそれが新しいものだと考えています。

- form_edit.fields_for :current_location do |location_form|
    = location_form.label :location, "Current Location"
    = location_form.text_field :location
    = location_form.hidden_field :id unless location_form.new_record?
于 2009-10-20T11:12:13.717 に答える
0

前の回答が本当に正しいかどうかはわかりません。必要なのは、場所自体ではなく、場所のユーザーの ID を指定することです。

- form_edit.fields_for :current_location do |location_form|
  = location_form.label :location, "Current Location"
  = location_form.text_field :location
  = location_form.hidden_field :user_id
于 2009-10-20T12:51:40.277 に答える