سؤال

لدي كيان مستخدم لديه حقل موقع حالي (المدينة والبلد). لعقد هذه المعلومات ، قمت بإنشاء كيان يسمى موقع المستخدمين.

لست متأكدًا تمامًا مما إذا كان ينبغي عليّ وضع نموذج المستخدم "HAS_ONE" أو "ينتمي إلى" ، لكن لما قرأته إذا أردت أن يكون للمفتاح الخارجي للموقع الذي يجب أن أضعه "ينتمي إلى". أريد أيضًا أن أكون قادرًا على تحرير الموقع الحالي للمستخدم عند تحرير المستخدم. لذلك أنا أستخدم سمات متداخلة. ولكن عندما أقوم بتحرير المستخدم ، انتهى بي الأمر إلى إضافة موقع جديد في كل مرة دون ربطه بالمستخدم الذي تم تحريره. هل تستطيع مساعدتي؟

الكود الخاص بي هو ما يلي:

#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
هل كانت مفيدة؟

المحلول

المشكلة الدقيقة التي تواجهها ، كما أشار الآخرون هي أن وحدة التحكم الخاصة بك لا تتلقى معرف الموقع كما ينبغي. يبحث لي يتم تمرير معرف الموقع من خلال المعلمة الخاطئة. لسوء الحظ ، لا يوجد معرف الموقع في سجل جديد ، لذلك هذا غير ممكن في النموذج.

تنبع مشكلتك من الاستخدام لـ accounts_nested_attributes_for على العلاقة الانتماء. لم يتم تعريف السلوك بوضوح. يبدو أن هذا خطأ موثق. لذا ، يجب أن يكون القبول _nted_attributes_for على واحد أو له جانب العديد من العلاقة.

فيما يلي بعض الحلول الممكنة:

  1. انقل accounted_nested_attributes_for إلى نموذج الموقع وقم ببناء النماذج الخاصة بك في الاتجاه الآخر.

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

    لسوء الحظ ، هذا لا يسمح بطريقة منطقية لتقديم المعلومات. ويجعل تحرير المستخدم المناسب صعبًا.

  2. استخدم نموذج Join ، وجعله يحتوي على واحد: من خلال العلاقة.

    أنا بصراحة لست متأكدًا من مدى قبول work_attributes_for مع: من خلال العلاقة ، ولكنه سيحل مشكلتك بالتأكيد مع ربط السجلات.

  3. تجاهل قبول_nted_attributes_for والتعامل مع الارتباط في وحدة التحكم الخاصة بك بالطريقة القديمة.

    في الواقع ، احتفظ بـ accounts_nested_attributes_for. إنه يوفر بعض طرق الراحة المفيدة ، فقط لا تدعها تصل إلى بيان update_attributes/إنشاء.

    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 تلقائيًا ، إذا لم ينشئ موقعًا جديدًا. ومع ذلك ، يتطلب find_or_create_by_id ، إدخال معرف في التجزئة حتى يعمل. سيتم إنشاء معرف زيادة تلقائي بشكل صحيح إذا لم يكن المعرف موجودًا في قاعدة البيانات. إذا كنت تقوم بإنشاء موقع جديد ، فستحتاج إلى إضافته. أسهل لإضافته إلى النموذج مع =location_form.hidden_field :id, 0 unless current\_location.new\_record?.

ومع ذلك ، قد ترغب في تقليل إنشاء موقع مكرر ، وتغيير location.find_or_create_by_id إلى location.find_or_create_by_location. سيؤدي ذلك أيضًا إلى تقليل أي أخطاء من صحة التفرد الفاشلة.

نصائح أخرى

لا تقدم معرف السمة المتداخلة. لذا يعتقد ريلز أنها جديدة.

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

لست متأكدًا مما إذا كانت الإجابة السابقة صحيحة حقًا. ما تحتاجه هو تحديد معرف المستخدم للموقع ، وليس الموقع نفسه.

- 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

بشكل افتراضي belongs_to :current_location, :class_name => 'Location' سوف تتوقع Users الجدول لديه current_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!
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top