القضبان:تعارض الموارد المتداخلة، وكيفية تحديد نطاق إجراء الفهرس اعتمادًا على المسار المطلوب

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

سؤال

تخيل أن لديك طريقين محددين:

map.resources articles
map.resources categories, :has_many => :articles

كلاهما يمكن الوصول إليهما عن طريق المساعدين/المسارات

articles_path # /articles
category_articles_path(1) # /category/1/articles

إذا قمت بزيارة /articles, index العمل من ArticlesController يتم تنفيذ.

إذا قمت بزيارة /category/1/articles, index العمل من ArticlesController يتم تنفيذه أيضًا.

إذًا، ما هو أفضل أسلوب للاختيار المشروط للمقالات المحددة فقط اعتمادًا على مسار الاستدعاء؟

#if coming from the nested resource route
@articles = Articles.find_by_category_id(params[:category_id])
#else
@articles = Articles.all
هل كانت مفيدة؟

المحلول

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

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

class Articles

  before_filter :determine_scope

  def index
    @articles = @scope.all
    # ...
  end

  protected

    def determine_scope
      @scope = if params[:category_id]
        Category.find(params[:category_id]).articles
      else
        Article
      end
    end

end

والسبب في المتغيرscope هو أنك قد تحتاج إلى معرفة نطاق طلبك خارج عمل واحد. دعنا نفترض أنك ترغب في عرض عدد السجلات في وجهة نظركم. عليك أن تعرف ما إذا كنت يتم تصفية حسب الفئة أم لا. في هذه الحالة، يمكنك ببساطة تحتاج إلى استدعاء @scope.count أو @scope.my_named_scope.count بدلا من تكرار كل مرة الاختيار على params[:category_id].

وهذا النهج يعمل بشكل جيد إذا وجهات نظركم، واحد مع فئة واحدة دون فئة، هي مماثلة تماما. ولكن ماذا يحدث عندما إدراج تصفيتها حسب الفئة هي مختلفة تماما مقارنة مع واحد من دون فئة؟ يحدث هذا في كثير من الأحيان: يعرض القسم الفئة الخاصة بك بعض الحاجيات التي تركز على فئة بينما القسم مقالك بعض الحاجيات ذات الصلة المادة والتصفية. أيضا، وتحكم المادة لديه بعض before_filters خاص قد ترغب في استخدام، ولكن لم يكن لديك لاستخدامها عندما ينتمي إدراج المادة إلى فئة.

في هذه الحالة، قد ترغب في فصل الإجراءات.

map.resources articles
map.resources categories, :collection => { :articles => :get }

articles_path # /articles and ArticlesController#index
category_articles_path(1) # /category/1/articles and CategoriesController#articles

والآن تدار القائمة التي تمت تصفيتها حسب الفئة التي CategoriesController ويرث جميع المرشحات تحكم، وتخطيطات، وإعدادات ... في حين تتم إدارة الإدراج غير المرشحة من قبل ArticlesController.

وهذا عادة ما يكون خياري المفضل لأنك لم يكن لديك مع اتخاذ إجراءات إضافية لفوضى وجهات نظركم والتحكم مع طن من الشيكات المشروطة.

نصائح أخرى

كثيرا ما أحب أن أفصل بين تلك الأفعال.عندما تكون الإجراءات الناتجة متشابهة جدًا، يمكنك فصل النطاقات داخل وحدة التحكم بسهولة من خلال معرفة ما إذا كانت المعلمات [:category_id] موجودة وما إلى ذلك (راجع إجابة @SimoneCarletti).

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

في الطرق.rb:

resources categories do
  resources articles, :except => [:index] do
    get :index, :on => :collection, :action => 'index_articles'
  end
end
resources articles, :except => [:index] do
  get :index, :on => :collection, :action => 'index_all'
end

ثم يمكنك الدخول المقالاتController.rb

def index_all
  @articles = @articles = Articles.all
  render :index # or something else
end

def index_categories
  @articles = Articles.find_by_category_id(params[:category_id])
  render :index # or something else
end

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

if params[:category_id]
  @articles = Category.find(params[:category_id]).articles
else
  @articles = Article.all
end

ومع ذلك، اعتمادا على ما غيرها من الموارد متداخلة لديك لنموذج، وإصرارها على هذا النهج يمكن الحصول على مملة جدا. في هذه الحالة، وذلك باستخدام البرنامج المساعد مثل resource_controller أو <وأ href = "http://github.com / hcatlin / make_resourceful "يختلط =" نوفولو noreferrer "> سوف make_resourceful جعل هذا أبسط من ذلك بكثير.

class ArticlesController < ResourceController::Base
  belongs_to :category
end

وهذا سوف تفعل في الواقع كل شيء كنت تتوقع. فهو يوفر لك جميع الإجراءات راحة القياسية وتلقائيا الإعداد نطاق /categories/1/articles.

if params[:category_id].blank?
  # all
else
  # find by category_id
end

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

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