You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails实现Freelancer列表价格范围过滤(保留featured排序)及表单错误修复咨询

Fixing Price Range Filtering & Form Error While Preserving Freelancer Sort Order

Let's break down your issues one by one and get this working properly:

1. Fix the Form Error (undefined local variable or method 'index')

The form_for helper is designed for working with ActiveRecord model instances, but your filter inputs are just query parameters—not attributes of a Freelancer object. Passing index (a controller action name) to form_for is why you're seeing that error.

Replace your form with form_tag (made for non-model forms) pointing to your home index route, and use number_field_tag for the price inputs (since cost is a numeric value):

<%= form_tag home_path, method: :get do %>
  <div class="mb-3">
    <%= label_tag :cost_greater_than, "Minimum Price:" %>
    <%= number_field_tag :cost_greater_than, params[:cost_greater_than], min: 0, step: 0.01 %>
  </div>
  <div class="mb-3">
    <%= label_tag :cost_lower_than, "Maximum Price:" %>
    <%= number_field_tag :cost_lower_than, params[:cost_lower_than], min: 0, step: 0.01 %>
  </div>
  <%= submit_tag "Filter", class: "btn btn-primary" %>
<% end %>
  • form_tag home_path targets your HomeController#index action with a GET request (ideal for filters, as it keeps parameters in the URL for bookmarking/sharing).
  • We pre-fill inputs with params[:cost_greater_than] and params[:cost_lower_than] so filter values persist after submission.

2. Fix the Parameter Mix-Up in Your Controller

You have a critical typo in your where clauses—you swapped cost_greater_than and cost_lower_than! That would have reversed your filter logic entirely. Here's the corrected controller code:

class HomeController < ApplicationController
  before_action :set_freelancer, only: %i[ show edit update destroy ]

  def index
    # Start with your existing sort order (featured freelancers first)
    freelancers_scope = Freelancer.order(featured: :desc)

    # Apply price filters only if the corresponding param is present
    if params[:cost_greater_than].present?
      freelancers_scope = freelancers_scope.where("cost >= ?", params[:cost_greater_than])
    end
    if params[:cost_lower_than].present?
      freelancers_scope = freelancers_scope.where("cost <= ?", params[:cost_lower_than])
    end

    # Paginate the final filtered/sorted scope
    @pagy, @freelancers = pagy(freelancers_scope)
  end

  # ... rest of your private methods
end

This ensures we first sort freelancers by featured: :desc, then apply price filters on top of that sorted set—exactly matching your core requirement.

3. Using has_scope Safely (Without Breaking Your Sort)

You were right to be cautious, but has_scope won't mess up your sort order if you structure things correctly. The key is to define your base sort after applying scopes, or ensure scopes don't override existing ordering. Here's a clean implementation:

Step 1: Add scopes to your Freelancer model

class Freelancer < ApplicationRecord
  scope :cost_greater_than, ->(amount) { where("cost >= ?", amount) }
  scope :cost_lower_than, ->(amount) { where("cost <= ?", amount) }
end

Step 2: Update your controller to use has_scope

class HomeController < ApplicationController
  before_action :set_freelancer, only: %i[ show edit update destroy ]
  has_scope :cost_greater_than, type: :numeric
  has_scope :cost_lower_than, type: :numeric

  def index
    # Apply scopes first, then enforce your sort order
    freelancers_scope = apply_scopes(Freelancer).order(featured: :desc)
    @pagy, @freelancers = pagy(freelancers_scope)
  end

  # ... rest of your code
end

By chaining order after apply_scopes, you ensure your featured-first sort takes precedence over any scopes (scopes won't modify existing ordering unless explicitly coded to). This keeps your original sort intact while adding filter functionality.

Final Notes

  • Use GET requests for filters: This lets users bookmark or share filtered results easily.
  • Sanitize numeric params (optional): For extra safety, convert params to floats with params[:cost_greater_than].to_f—the has_scope type: :numeric option does this automatically.
  • Test edge cases: Verify filtering works when only one price input is filled, or both are empty (should return all sorted freelancers).

内容的提问来源于stack exchange,提问作者Luke Czoboriek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 00:42:36