我的用户正在提交包含多个项目的请求。无论项目如何保存到SQL数据库中,为了便于分析,我需要解析每个项目并将其保存为Excel文件(Google Drive)中的单个数据行。
换句话说,在SQL中,请求看起来像这样:{:name => "john", :email => "john@gmail.com", :items => ["a", "b", "c"]
,但我需要将其转换为每个项目有3行的文档,并且行中唯一不同的是项目。
我下面的作品,但我想知道它是否最有效,从以下角度来看:
谢谢!
模型代码
class Request < ActiveRecord::Base
serialize :items
validate :must_have_one_item
def must_have_one_item
errors.add(:items, 'You must select at least one item') unless self.items.detect { |i| i != "0" }
end
end
查看代码
<%= f.check_box(:items, {:multiple => true}, "#{thing}") %>
<%= f.label(:items, "#{thing}") %>
这里,thing
是迭代器函数的一部分,它通过预定义的潜在项目列表来运行。
CONTROLLER代码,有很多评论!
class RequestsController < ApplicationController
def new
@requestrecord = Request.new
end
def create
@requestrecord = Request.new(request_params)
if @requestrecord.save
# Given model/ form code so far, the items are passed through as an array. The remaining comments uses the example: @requestrecord.items = ["water filter", "tent", "0", "0", "0"]. What happens is that "0" represents blank checkboxes
@requestrecord.items.select! { |x| x != "0" } #removes blank checkboxes; @requestrecord.items = ["water filter", "tent"]
num_of_requests = @requestrecord.items.count #counts number of items requested; num_of_requests = 2
i = 0
cloned_request = Hash.new
while i < num_of_requests do
cloned_request[i] = Marshal.load(Marshal.dump(@requestrecord)) #creates a cloned_request[0] = @requestrecord and cloned_request[1] = @requestrecord
cloned_request[i].items = @requestrecord.items.slice(i) #disaggregates the items into the cloned_requests; cloned_request[0].items = "water filter", cloned_request[1].items = "tent"
i += 1
end
cloned_request.each do | key, request |
request.save_spreadsheet
end
else
render 'new'
end
end
private
def request_params
params.require(:request).permit({:items => []})
end
end
答案 0 :(得分:2)
好的,所以这里有很多问题。
首先,尝试永远不要在数据库中存储数据数组,因为您似乎正在使用serialize :items
。您可以详细了解here的原因。你应该做的是拥有一个名为Item
的模型,它有自己的表。从那里,您可以使用更多模型将其与其他模型相关联,例如具有item_id和user_id属性为整数的UserItem
模型。此UserItems是您的关联模型,它包含有关项目和用户如何关联的信息(即哪些用户具有哪些项目)。如果需要关联请求和项目,您也可以创建RequestItem模型。
当用户提交项目列表时,您可以从params[:request][:items]
哈希中获取每个项目并使用
params[:request][:items].each do |item|
UserItem.create(user_id: @user.id, item_id: item.to_i)
end
请注意,它显示为item.to_i
。这是因为,一旦你有了Items表,每个项目都会有一个id。一旦您更改视图以向您发送item_id(而不是项目名称),您就可以使用上述逻辑轻松地为其创建UserItem。 (使用to_i是因为大多数时间数据是作为字符串发送的,您需要将其转换为整数)。
其次,您真的应该将业务逻辑移动到适当的模型,或者至少是帮助者。作为一个原则,你的控制器应该“瘦”,你的模型应该“胖”。这有很多原因,但在我看来,最重要的原因是它使您的代码更容易测试。您可以阅读有关此here的更多信息。
答案 1 :(得分:0)
同意Enraged Camel
- 我认为您可以提高create
方法效率:
#app/controllers/requests_controller.rb
Class RequestsController < ApplicationController
def create
items = params[:request][:items]
if items.kind_of?(Array)
#means there are multiple array items
for item in items do
request = Request.new(your: item[:attribute], and: item[:another_attribute])
request.save
end
else
request = Request.new(request_params)
request.save
end
end
private
def request_params
request.require(request).permit(:your, :attributes)
end
end
不要偷窃 任何人的雷声;希望你能从我发布的内容中获得更多想法!