假设:我想要32个部分,每个部分有4个“槽”。每个插槽都可以从可拖动列表中保存一个人。
什么是保存位置(并回忆每个用户)保持空位或“位置”在适当位置的最佳方法?
现在,我有类似提供的小提琴,但保存后,我只是将data-id
作为数组发送,因此它保存了他们的订单,但没有考虑空白空间。 ..当然,我回读列表的方法只返回数组。即。如果我有,在创建时:Tim,空,Bob,清空我的控制器保存['Tim', 'Bob']
当用户重新加载时,他们看到:Tim,Bob,空,空
所以这是一个双面的问题:
1)如何保存用户列表包括空白以及使用rails / mongoid执行此操作的最佳方法是什么? 同样,我目前知道如何保存,我只是不知道是否更好地使用数组/对象或什么......
2)如何正确重建/读取/加载列表?
Fiddle:想象一下,这还有31个其他部分需要填写...这只是一个部分。
修改
如果我使用像acts_as_list
这样的宝石,那么每个用户的项目有一行会不会(因为每个用户将有128个条目)?在我看来,这将使mongo集合有太多的文件,但我对mongodb的理解也很差。
user_id,
pick_id,
position
而不是
user_id,
picks [
"pick_id_1234",
"pick_id_1235",
"pick_id_1236"
]
答案 0 :(得分:2)
我没有使用过Mongoid,因此我无法为该部分提供具体的编码;但我可以给你一些结构性的想法
<强>保存强>
无论如何,您仍需要以某种方式保存列表
因为你没有给出足够的上下文,我会假设你想永久保持列表的状态(使用数据库)。如果您希望列表是临时的(I.E您希望在步骤之间移动等),我建议sessions
<强> DB 强>
如果要保存到数据库,则该过程相对简单。我会在这里使用标准的ActiveRecord,因为我不知道mongoid(对不起):
<强>模型强>
#app/models/list.rb
Class List < ActiveRecord::Base
belongs_to :section
belongs_to :user
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :lists
end
#app/models/section.rb
Class UserListPosition < ActiveRecord::Base
has_many :lists
has_many :users, through: :lists
end
<强>架构强>
users
id | name | email | created_at | updated_at
sections
id | details | about | section | created_at | updated_at
lists
id | section_id | user_id | created_at | updated_at
<强>控制器强>
#app/controllers/lists_controller.rb
def new
@list = 32.times do { List.new } ##needs refactoring
end
def create
@list = List.new(list_params)
@list.save
end
private
def list_params
params.require(:list).permit(:section_id, :user_id)
end
<强>视图强>
#app/views/lists/new.html.erb
<%= form_for @list do |f| %>
<% Section.all.each do |section| %>
##inputs here
<% end %>
<%= f.submit %>
<% end %>
答案 1 :(得分:2)
您分配给插槽的对象始终是同一个类Person。
如果是这样,那么一种方法就是使用一个简单的Struct,因为你声明它需要保留空白。
# /struct/slotter.rb
Slotter = Struct.new(:section_id, :slot1, :slot2, :slot3, :slot4)
# assuming slots are always the Person#id, i.e. Integer representation
# of person by their id. Also would work with UUIDs or BSON, etc.
# The section number would be stored in the variable *section_no*
Slotter.new(section_no, id_1, id_2, id_3, id_4)
# You can also pass a block to a Struct so you could write read
# accessors for the data, again this assumes Person class exists
Slotter = Struct.new(:section_id, :slot1, :slot2, :slot3, :slot4) do
def read_slot1
Person.find(slot1)
end
end
文件系统独立于此,因为这将为您提供具有适当Marshal.dump和加载的对象,以便您可以从任何数据库中保存或加载。
由于您的应用程序使用的是Javascript,因此如果在Rails应用程序中使用,则可以将其转换为JSON,因为它具有正确的to_json。如果你需要不同的根节点等,也可以写一个to_json。
这个问题本质上是一个位掩码问题。如果您可以重新格式化您的问题,您可能只需创建一个整数列,并将您的Person类数据存储在一个简单的Integer列中。我会告诉你弄清楚那一个。 :)
此应用程序可能更适合作为JavaScript应用程序,例如在Angular.js中,使用Rails后端来持久存储到数据库中。这样,您就可以在客户端中动态修改巨型JSON对象,并且负载将远离您的服务器。
关于位掩码方法。这是使用Plain Old Ruby Object将位掩码包装/解包为整数的一种方法。它松散地基于Railscast。
This particular approach仅利用位掩码来存储节的插槽值。尽管如此,可以应用相同的方法来存储多达n个值。关键是SLOTS阵列基本上是一样的。您可以添加到右侧,例如slot5在slot4的右边,但不能改变它的顺序。
主要限制是
另一个好处是你可以存储一个heckuva很多只有一个整数来补偿IMO。因此,如果你想获得所有拥有x属性集的玩家,你需要一个方法,如:
def in_slot?(slot)
slots.include?(slot.to_s)
end
你仍然可以获得你在代码与SQL中必须完成的统计数据。即在数组上映射(在ruby中)。就这样:
all.keep_if {|p| p.is_slot?(:slot1)}
但是,如果你知道你正在寻找的面具,例如。在示例中我们想要所有slot1和slot3然后我们知道掩码是 5 所以你只需要查找slot_mask为5的所有条目。
如果你在路上发现你需要更高级的功能,即掩码解决方案的管理比在SQL中存储你的值更慢。您可以随时将掩码展开到一个新的解决方案中,例如序列化或更正式的子类,并在对象Array上快速映射。
答案 2 :(得分:1)
我认为您的问题有两个部分:1。您需要为前端的每个部分存储各种列表2.然后以保留所有数据(包括空白)的方式将这些列表存储在您的数据库中)所以你可以在将来重新创建相同的视图。
我会尝试分别回答每个部分,然后让您了解它们是如何结合在一起的。
现在找到解决方案!
前端
我建议做的是在视图中维护一个JSON对象,该对象包含所有选择的值(无论是null还是填充)。所以我对你的小提琴进行了一些修改,给你一个简单的例子:http://jsfiddle.net/3SSqM/41/(道歉,这里的一些代码不是很强大,而且在windows.document上存储变量真是不好的做法,但我只是想快速煽动一些可以证明这是如何工作的东西。以下是小提琴中值得注意的事项:
indexes
的JS对象维护所有选择列表,每个键都是0-127的id,所以第一部分的第一个槽的id为0,第四个槽位于第32个部分的id为127 当拖动事件结束时,您可以获取部分名称(即从表ID中提取NUMBER),然后使用所有选择的数据ID填充JS对象。我认为你应该这样做的方式如下:
$('.picks-group').sortable({
tolerance: "pointer",
start: // some code
stop: function (event, ui) {
sorting = false;
sectionNumber = getSectionNumber($(this)[0].id);
$(this).find('li').each(function (i, obj) {
var index = sectionNumber + i;
indexes[String(index)] = $(obj).attr('data-id');
});
},
change: // some code
});
请注意,这将保留'nulls',这正是您想要的。当用户完成选择时,您可以将indexes
JSON对象发送到Rails,这应该非常简单。在rails中使用JSON解析器将JSON对象转换为哈希值。
后端
现在,将这些数据存储在Mongoid中的方式是另一个有趣的问题。这实际上取决于您打算如何使用数据。如果您打算将所有数据存储到下次用户访问您的Web应用程序然后重新呈现他/她的选择,那么我将继续将整个对象存储为哈希的一个属性。类似的东西:
Class Pick
include Mongoid::Document
field :picks, type: Hash
end
这么简单!你不喜欢mongoid吗?
但是如果你打算查询数据,比如试图找出最佳选择者,那么这可能并不理想。现在可能性非常大,模式实际上取决于您的用例,这里有一些注意事项:
因此,如果您需要知道第一个插槽中第一部分最受欢迎的选择,您可以执行以下操作:
Class Pick
include Mongoid::Document
field :pick_0
field :pick_1
# ... you get the idea
field :pick_127
end
顺便说一下,实际上没有列出pick_0到pick_127的每个属性,我只是这样做是为了让你知道我的意思,如果你想沿着这条路走下去使用动态属性,如下所述:{{3 }}
重新发布视图
最后一件事你很好奇:如何在下次用户登录时重新创建视图。这取决于你如何存储数据,但是假设你将整个事物存储为哈希,在查看您只是迭代存储在哈希中的所有不同键值对并呈现您的表。这部分应该非常直接。
答案 3 :(得分:-1)
将列表另存为用户ID数组。使用Mongodb,这个数组通常会嵌入到用户文档中。
使用null
s填充数组来表示空格,因此Tim,空,Bob,空在JS / Mongodb中变为['Tim', null, 'Bob', null]
或使用用户ID保存位置ID,因此您拥有{ {1}}。哪一个更有效取决于平均有多少个插槽留空。使用[[0, 'Tim'], [2, 'Bob']]
可能会更容易,所以我赞成它,其他条件相同。