الجمعيات متعددة الأشكال القضبان بالإضافة إلى الطرق

StackOverflow https://stackoverflow.com/questions/2071979

سؤال

لدي نموذج ، تقرير ، وهو متعدد الأشكال. قد يكون لدى الكثير من العوامل في موقعي الكثير منها.

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

في طريقي ، أنا أفعل شيئًا مثل

map.resources :users, :has_many => [ :reports ]
map.resources :posts, :has_many => [ :reports ]

لكن في تقريري _controller ، أود الحصول على العلاقة من قبل.

مثل:

before_filter :get_reportable

def get_reportable
   reportable = *reportable_class*.find params[:reportable_id]
end

هل هذا ممكن؟

كيف يمكنني الحصول على تقرير _class و identable_id؟

يمكنني الحصول على params [: user_id] عندما يأتي من وحدة تحكم المستخدمين ، أو params [: post_id] عندما يأتي من المنشورات. يمكنني القيام بحالة مع كل العلاقات ، لكنها لا تبدو حلًا نظيفًا على الإطلاق ...

وجود جمعية متعددة الأشكال سيكون الأفضل ، هل هناك أي كيفية؟

هل كانت مفيدة؟

المحلول

إذا كان لديك وحدة تحكم واحدة تعالج الطلبات من خلال مسارين مختلفين ، فأنت بحاجة إلى إدراكها للسياقات التي سيتم استدعاؤها. غالبًا ما ترى الكثير من التعليمات البرمجية التي تبدو مثل هذا:

before_filter :load_reportable

def load_reportable
  if (params[:user_id])
    @user = User.find(params[:user_id])
    @reportable = @user
  elsif (params[:post_id])
    @post = Post.find(params[:post_id])
    @reportable = @post
  end
rescue ActiveRecord::RecordNotFound
  render(:partial => 'not_found', :status => :not_found)
  return false
end

نظرًا لأنك تستخدم ارتباطًا متعدد الأشكال ، فقد تتمكن من القيام بشيء مثل هذا بدلاً من ذلك:

before_filter :load_reportable

def load_reportable
  unless (@reportable = @report.reportable)
    # No parent record found
    render(:partial => 'not_found', :status => :not_found)
    return false
  end

  # Verify that the reportable relationship is expressed properly
  # in the path.

  if (params[:user_id])
    unless (@reportable.to_param == params[:user_id])
      render(:partial => 'user_not_found', :status => :not_found)
      return false
    end
  elsif (params[:post_id])
    unless (@reportable.to_param == params[:post_id])
      render(:partial => 'post_not_found', :status => :not_found)
      return false
    end
  end
end

إن المشكلة في هذا النهج ، حيث لديك وحدة تحكم واحدة تخدم طريقين مختلفين تمامًا ، هي أن إنشاء رسائل خطأ ، مثل "المستخدم لم يتم العثور عليه" مقابل "Post Not Found". قد يكون هذا أمرًا صعبًا إذا لم تكن ترث من المستخدمين :: basecontroller ، على سبيل المثال.

في كثير من الحالات ، من الأسهل إنشاء وحدات تحكم "تقريرين" مستقلين ، مثل المستخدمين/التقارير والمنشورات/التقارير ، حيث يتم استيراد أي وظيفة مشتركة من وحدة نمطية. عادة ما ترث وحدات التحكم هذه من وحدة تحكم قاعدة تنفذ التحميل والتعامل مع الأخطاء. يمكن لجهاز التحكم الأساسي أيضًا إنشاء تخطيط وعنوان الصفحة وما إلى ذلك ، دون الحاجة إلى إعادة تنفيذ هذه الوظيفة لكل وحدة تحكم من الموارد الفرعية.

البديل هو إلغاء تقارير التقارير وجعلها تعمل كوحدة تحكم خاصة بها حيث تكون العلاقة مع السجل "القابل للإبلاغ" غير ذي صلة في الغالب.

نصائح أخرى

أو حاول ذلك:

before_filter :get_reportable

def get_reportable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      @reportable = $1.classify.constantize.find(value)
    end
  end
end

إنها تمر بجميع المعلمات ويحاول العثور على نهاية واحدة مع _id ، ثم يمسك بذلك قبل الجزء ويجد السجل ذي الصلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top