使用Rails方法find_or_create_by时,它是属于模型还是控制器?我很难理解如何实际实现这个方法。
我希望我的rails应用程序接受来自用户的JSON消息。用户将数据发送回服务器,以便将其保存在数据库中。话虽这么说,我认为用户必须使用'POST'或'PATCH方法来存储或更新我服务器上的数据。当我查看我的路线时,创建动作使用'POST'方法。
我已经阅读了以下Rails文档,但它没有向我澄清任何内容。 http://guides.rubyonrails.org/active_record_querying.html#find-or-create-by
我会将find_or_create_by方法放在我的创建操作中吗?或者它属于其他地方?它在创建动作中似乎不正确......
class WifiNetworksController < ApplicationController
def create
@wifi_network = WifiNetwork.find_or_create_by(bssid: params[:bssid],
ssid: params[:ssid],
channel: params[:channel], etc...)
end
end
最终我想:
感谢您的时间!
最后更新 - 感谢大家的好建议!我不得不采取一些每个人的建议来让它工作!以下是我最终做的事情..好像没有错误。
def create
respond_to do |format|
if @wifi_network = WifiNetwork.find_by(bssid: wifi_network_params[:bssid])
# Logic for checking whether to update the record or not
@wifi_network.update_attributes(wifi_network_params) if @wifi_network.rssi < params[:rssi]
format.json { render :nothing => true }
else
# Must be a new wifi network, create it
@wifi_network = WifiNetwork.create(wifi_network_params)
format.json { render :nothing => true }
end
end
end
答案 0 :(得分:3)
如果您使用强力参数,您可以在控制器中执行此操作:
def create
@wifi_network = WifiNetwork.find_or_create_by(bssid: wifi_network_params[:bssid])
@wifi_network.update_attributes(wifi_network_params)
end
然后当用户做出如下的卷曲时:
curl -X POST localhost:3000/wifi_networks -d "wifi_network[bssid]=bssid1&wifi_network[ssid]=ssid1&wifi_network[channel]=channel1"
您的创建操作将通过它的bssid查找WifiNetwork并更新ssid和channel属性,或者如果它不存在,它将使用bssid param创建一个WifiNetwork,然后使用其余的更新新创建的记录的ATT。要小心,因为如果其他attrs的wifi_network_params为空,他们会将params更新为nil。
答案 1 :(得分:0)
我认为退一步并真正考虑应用程序的界面可能会很好。是否有任何特殊原因需要使用find_or_create_by
并在一个控制器操作中执行所有操作?
为什么不通过单独创建&#39;来简化和遵守REST。并且&#39;更新&#39;您WifiNetworksController
上的操作:
class WifiNetworksController < ApplicationController
def create
@wifi_network = WifiNetwork.new(wifi_network_params)
if @wifi_network.save
# success response
else
# failure response
end
end
def update
# params[:id] won't work here if the client sending the request doesn't know the id of the
# wifi network, so replace it with the attribute you expect to be able to
# uniquely identify a WifiNetwork with.
if @wifi_network = WifiNetwork.find(params[:id])
# Logic for deciding whether to update or not
@wifi_network.update_attributes(wifi_network_params) if @wifi_network.signal_strength < params[:signal_strength]
else
# wifi_network not found, respond accordingly
end
end
private
# strong_parameters for Rails 4
def wifi_network_params
params.require(:wifi_network).permit(:ssid, :channel,...)
end
end
然后,您可以在WifiNetwork
模型上进行验证,以确保某些属性是唯一的,以避免重复。
或者,如果您真的想要,可以将create
和update
合并为一个操作,但create
可能不是语义上的最佳名称。
编辑:在您的评论提供了一些背景信息之后,使用find_or_create_by可能没什么好处,因为您无法判断返回的记录是否已创建&#39;或者&#39;检索&#39;,这将允许您避免对其进行冗余更新操作。
假设bssid
属性始终是唯一参数:
def create
if @wifi_network = WifiNetwork.find(params[:bssid])
# Logic for checking whether to update the record or not
@wifi_network.update_attributes(wifi_network_params) if @wifi_network.signal_strength < params[:signal_strength]
else
# Must be a new wifi network, create it
@wifi_network = WifiNetwork.create(wifi_network_params)
end
end