如何对 Rails 控制器中的数组中的某些值进行排序?

发布于 2024-08-24 23:29:44 字数 812 浏览 2 评论 0原文

我有一个链接数组,我正在将其保存到数据库中。问题是记录没有按照数组的顺序保存,即 links[1] 在 links[2] 之前保存,依此类推...

这是视图文件中的示例:

<p>
  <label for="links_9_label">Label</label>
  <input id="links_9_name" name="links[9][name]" size="30" type="text" />
  <input id="links_9_url" name="links[9][url]" size="30" type="text" />
</p>

这是我的控制器:

def create
    @links = params[:links].values.collect { |link| @user.links.new(link) }

    respond_to do |format|
         if @links.all?(&:valid?)
         @links.each(&:save!)

        flash[:notice] = 'Links were successfully created.'
        format.html { redirect_to(links_url) }
      else
        format.html { render :action => "new" }
      end
    end
  end

谢谢提前!

阿尔弗雷德

I've got a links array that I'm saving to a database. The problem is that the records aren't saved in the order of the array ie links[1] is saved before links[2] and so on...

This is a example from the view file:

<p>
  <label for="links_9_label">Label</label>
  <input id="links_9_name" name="links[9][name]" size="30" type="text" />
  <input id="links_9_url" name="links[9][url]" size="30" type="text" />
</p>

And this is my controller:

def create
    @links = params[:links].values.collect { |link| @user.links.new(link) }

    respond_to do |format|
         if @links.all?(&:valid?)
         @links.each(&:save!)

        flash[:notice] = 'Links were successfully created.'
        format.html { redirect_to(links_url) }
      else
        format.html { render :action => "new" }
      end
    end
  end

Thanks in advance!

Alfred

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雾里花 2024-08-31 23:29:44

您的链接未按顺序存储的原因是您没有按顺序将它们呈现给数据库。

-- param 对象不是一个数组,尽管在某种程度上它可能看起来像一个数组。相反,它们是一个哈希,其中键是整数。 你需要使用

params[:links].values.collect

你可以说这是真的,因为如果它是一个数组,

params[:links].collect

,你会使用任何时候你使用 .values 方法,键顺序是不确定的。

解决方案

我同意@pg的观点,即您在使用 db id 作为订单时应该非常小心。例如,假设您想稍后更改订单?我经常将“list_order”作为模型中的字段。

要重新排序参数并按键的顺序保存,请尝试以下操作:

links_param = params[:links]
ordered_keys = links_param.keys.sort
@links = ordered_keys.collect {|key| @user.links.new(links_param[key])}

添加:另请注意,键很可能以字符串形式出现,而不是整数。因此,如果您有超过 10 个,可能需要将它们按整数排序:

ordered_keys = links_param.keys.sort{|a,b| a.to_i <=> b.to_i}

添加是为了响应有关保存“display_order”的评论 -

首先,向模型添加新字段:display_order 。请务必在该字段上添加索引,因为您将对其进行排序。

然后,在您的控制器中,您需要公开模型的密钥。例如这样的:

 links_param = params[:links]
 links_params.keys.each{|key|links_params[key][:display_order] = key.to_i}

现在,当您构建 user.link 对象时,也会设置 display_order 参数。

The reason your links aren't being stored in order is that you're not presenting them to the db in order.

-- The param object is not an array, even though, to an extent it might look like one. Rather, they are a hash where the keys are integers. You can tell this is true because you need to use

params[:links].values.collect

if it was an array, you'd use

params[:links].collect

Any time you use .values method, the key order is indeterminate.

Solution

I agree with @p.g that you should be very careful about using db id's as an order. Eg suppose you want to change the order later? I often have 'list_order' as a field in my models.

To reorder the params, and save in order of the key, try the following:

links_param = params[:links]
ordered_keys = links_param.keys.sort
@links = ordered_keys.collect {|key| @user.links.new(links_param[key])}

Added: also note that the keys might well come in as strings, not integers. So if you have more than 10 of them, might be an idea to sort them as integers:

ordered_keys = links_param.keys.sort{|a,b| a.to_i <=> b.to_i}

Added in response to comment about saving the "display_order" --

First, add new field to model, :display_order. Be sure to add an index on the field since you'll be sorting on it.

Then, in your controller, you need to expose the key to the model. Eg something like this:

 links_param = params[:links]
 links_params.keys.each{|key|links_params[key][:display_order] = key.to_i}

Now when you build your user.link object, the display_order param will be set too.

千笙结 2024-08-31 23:29:44

更改您的架构,使其具有 display_order 列或类似的内容,并将其作为前端的隐藏输入推送。

不鼓励依赖 id 列进行排序,因为它本质上是数据库创建的任意值,大多数恰好遵循逻辑序列。为订单设置单独的列不会破坏 DRYness,因为它(从技术上讲)用于不同的目的。

Alter your schema so it has a display_order column or something similar, and have this pushed through as a hidden input on the front end.

Relying on the id column for ordering is discouraged, as it is essentially an arbitrary value created by the DB, which happens to follow a logical sequence most of the time. Having a separate column for the order won't break DRYness because it is (technically) for a different purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文