我正在使用Rails 5API构建一个用于检索数据的应用程序。我希望使用多个GET参数来提取数据。
示例获取请求格式
/users?company=Samsung&position=Engineer单参数控制器代码:-
def index
client = User.where("company = ?", params[:company])
render json: client
end多参数控制器代码:-
def index
client = User.where("company = ?", params[:company]).where("position = ?", params[:position])
render json: client
end同样,GET请求中可能包含/可能不包含许多参数。
我想要什么
如果用户没有指定任何参数,则应该向所有用户显示他。如果仅指定了几个参数,则只应搜索这些参数。
发生了什么
如果用户仅指定GET请求中的位置参数,Rails无法处理该参数&因为没有为其指定规则,因此会显示一个空白的json。
请注意,有许多参数,不可能为每个参数组合编写规则。
发布于 2016-08-27 01:02:58
解决方案的基本问题是,它迫使每个地方依次执行。这意味着,如果公司参数是nil,您将得到一个空关系,之后的所有where语句都将返回一个空关系。只有在提供了参数时,才需要有条件地筛选。
您要做的最好是在查询/搜索或筛选对象中完成(查询获取参数并返回结果集,筛选器接受已经生成的集合并对其进行过滤)。我喜欢在app/services/中定义它们,尽管有些人将它们放在app/queries中。
但是,方法中存在一些不一致之处,索引端点应该返回对象列表。即使您希望返回一个选项,您也应该期望有多个选项。假设我们修复索引端点并使用filter对象。
# app/controllers/users_controller.rb
def index
users = User.where(1=1)
users = Users::Filter.call(users, params)
render json: users
end您会注意到我使用User.where(1=1),这是因为我习惯于处理rails 3,如果使用User.all,rails 3返回数组而不是关系。
# /app/services/users/filter.rb
class Users::Filter
def self.call(resources, options)
new(resources, options).filter
end
private
attr_reader :resources, :options
def initialize(resources, options)
@resources = resources
@options = options
end
def filter
if options[:company]
@resources = resources.where(company: options[:company])
end
if options[:position]
@resources = resources.where(position: options[:position])
end
resources
end
end我之所以使用call (然后调用私有initialize和filter方法),是因为这个类没有被错误地使用。它只有一个入口点,并返回结果集。这也允许我将我的过滤功能分解成易于更改的小块咬合大小的块。
对于这个例子,我在filter中完成了所有的过滤,但是您可以将它们分解为方法,甚至可以使用一些聪明的元编程来调用过滤器名称,如果对象响应它的话。
编辑:
您还可以考虑找到一个类似于ransack1的gem解决方案,它允许您直接将参数传递给对象并搜索它。有许多不同类型的搜索/过滤宝石,以满足您的需要。
https://stackoverflow.com/questions/39176005
复制相似问题