首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Ruby on Rails将元素添加到序列化字段的数组中

问如何使用Ruby on Rails将元素添加到序列化字段的数组中
EN

Stack Overflow用户
提问于 2019-03-23 01:40:30
回答 3查看 355关注 0票数 0

在我的MySQL数据库中,有一个名为query_data的字段被定义为text。

在我的模型中,我将这个字段定义为serialize :query_data, JSON。

我要保存和检索JSON格式如下:

代码语言:javascript
复制
{:items => [
  {:id => 1},
  {:id => 2},
  {:id => 3}
]}

我有一个包含对象数组的集合(在本例中称为items)。

我想知道,添加或删除项目的最佳方法是什么。

示例:从我的项目列表中删除{:id => 2}并添加`{:id => 4}

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-26 20:09:27

基于@veridian-dynamics (感谢您的帮助!)这是我所做的。

型号:

代码语言:javascript
复制
class MyModel < ApplicationRecord
  serialize :item_data, JSON
end

控制器:

代码语言:javascript
复制
class ItemController  < ApplicationController
  before_action :authenticate_user!

  def add_item
    begin

      mymodel = MyModel.find_or_create_by(id: param[:model_id])

      if mymodel .item_data.blank?
        item = {:items => []}
      else
        item = mymodel.item_data.deep_symbolize_keys
      end

      bookmark_exist = item[:items].any? {|i| i[:id] == params[:id]}
      if !bookmark_exist
        item[:items] = item[:items ].append({id: params[:id]})   # adding a new item
      end

      mymodel.item_data = item
      mymodel.save

      return render :json => item, :status=> 200    

    rescue Exception => e
      return render :json =>{:errors=>e.message}, :status=> 400
      puts "ERROR: #{e.message}"
    end
  end

  def delete_item
    begin

      mymodel = MyModel.find_by(id: params[:model_id])
      if mymodel.present? && mymodel.item_data.present?
        item = mymodel.item_data.deep_symbolize_keys

        item[:items] = (item[:items].select { |itm| itm[:id] != params[:id] })   # remove an item
        mymodel.item_data =  item    
        mymodel.save

        return render :json => item, :status=> 200    
      end
    rescue Exception => e
      return render :json =>{:errors=>e.message}, :status=> 400
      puts "ERROR: #{e.message}"
    end
  end

end
票数 0
EN

Stack Overflow用户

发布于 2019-03-23 02:00:34

Ruby on Rails有一些很好的方法可以在JSON和Ruby之间无缝转换。

代码语言:javascript
复制
thing = {:items => [
  {:id => 1},
  {:id => 2},
  {:id => 3}
]}
thing.to_json # "{\"items\":[{\"id\":1},{\"id\":2},{\"id\":3}]}"

thing.to_json本质上是序列化程序中正在发生的事情。如果你想让它们回到Ruby,你可以这样做:

代码语言:javascript
复制
@items = @thing.query_data
JSON.parse(@items) # "items"=>[{"id"=>1}, {"id"=>2}, {"id"=>3}]}

现在我们可以很容易地在这两者之间切换,让我们只使用Ruby语法来处理添加和删除键。

代码语言:javascript
复制
thing = {:items => [
  {:id => 1},
  {:id => 2},
  {:id => 3}
]}
thing[:items] = thing[:items].append({:id => 4})   # adding a new item
thing[:items] = thing[:items].select { |item| item[:id] != 2 } # removing an item
票数 1
EN

Stack Overflow用户

发布于 2019-03-23 02:36:16

第一: serialize的第二个参数应该是存储在字段中的对象的类。您应该使用serialize :query_data, Hash。

除此之外,实际上还没有任何处理序列化数据的最佳实践。这在很大程度上取决于你的数据结构。您可能会问:“从散列中添加或删除项的最佳方法是什么?”

但是,由于这是一个散列,所以您应该确保将dirty attributes放在心上。如果你要做类似这样的事情:

代码语言:javascript
复制
items = my_model.query_data[:items]
items.reject! {|item| item[:id] == 2}
items += {id: 4}

那么模型就不会知道query_data发生了变化,应该在保存时进行更新。

代码语言:javascript
复制
my_model.changed?
# => false
my_model.save
# Won't actually save changes to db.

要避免这种情况,您可以:

A)确保您只直接设置my_model.query_data

B)在更改该字段后显式调用my_model.query_data_will_change!,以便在保存时正确更新。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55305116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档