在Rails 7中使用MongoDB的枚举器

huangapple go评论65阅读模式
英文:

Use Enumerators in Rails 7 with MongoDB

问题

I'm building a new project with Rails 7 and MongoDB 8. And I wanted to use enumerators for multiple fields ( states etc .. )

我正在使用Rails 7和MongoDB 8构建一个新项目。我想要为多个字段(状态等)使用枚举。

I wanted to use the gem mongoid-enum but it doesn't work with Mongo 8.

我想使用mongoid-enum宝石,但它不适用于Mongo 8。

Is switching to SQL database a solution? Or is there any other way?

切换到SQL数据库是一个解决方案吗?还是有其他方法?

I've checked on Mongo's doc and found a Phantom Custom Field Types but it looks like it's not saving in the db. In the rails console, I'll do the Model.status = "open" then saving it, it doesn't return any errors. So I close the console then open it again. Run the Model.status and it returns nil.

我查看了Mongo的文档,并找到了幻象自定义字段类型,但看起来它在数据库中没有保存。在rails控制台中,我执行Model.status = "open",然后保存它,没有返回任何错误。所以我关闭控制台,然后再次打开它。运行Model.status,它返回nil。

Thank you for reading and trying to help me!

谢谢你阅读并尝试帮助我!
1: https://www.mongodb.com/docs/mongoid/current/reference/fields/#phantom-custom-field-types

英文:

I'm building a new project with Rails 7 and MongoDB 8. And I wanted to use enumerators for multiple fields ( states etc .. )

I wanted to use the gem mongoid-enum but it doesn't work with Mongo 8.

Is switching to SQL database a solution ? Or is there any other way ?
I've checked on Mongo's doc and found a Phantom Custom Field Types but it looks like it's not saving in the db. In the rails console, I'll do the Model.status = "open" then saving it, it doesn't return any errors. So I close the console then open it again. Run the Model.status and it returns nil.

Thank you for reading and trying to help me !

答案1

得分: 0

以下是您要的内容的中文翻译:

首先,无论是 MongoDB 还是 PostgreSQL,都有优点和缺点,这取决于您需要的功能类型,参见:https://www.geeksforgeeks.org/difference-between-postgresql-and-mongodb/

关于“Phantom Custom Field Types”,这确实与 ActiveRecord::Enum 做了相同的事情,但需要编写更多的代码。您能否分享一下您用于测试的不起作用的代码?

编辑于 2022年7月2日:

以下是一个示例,演示如何在 MongoDB 中使用枚举而无需编写太多代码:

module MongoEnum
  # 获取应用程序范围的值并将其转换为数据库中的存储方式。将无效值转换为 nil。
  def mongoize(object)
    mapping[object]
  end

  # 获取数据库中存储的值,并将其转换为应用程序范围的值。将无效值转换为 nil。
  def demongoize(object)
    inverse_mapping[object]
  end

  # 将供应给条件的对象转换为查询友好的形式。将无效值返回为原值。
  def evolve(object)
    mapping.fetch(object, object)
  end

  def mapping
    @mapping ||= self.const_get(:MAPPING).freeze
  end

  def inverse_mapping
    @inverse_mapping ||= mapping.invert.freeze
  end
end

class RoleEnum
  extend MongoEnum

  MAPPING = {
    'admin' => 0,
    'user' => 1,
  }.freeze
end

class ColorEnum
  extend MongoEnum

  MAPPING = {
    'black' => 0,
    'white' => 1,
  }.freeze
end

class Profile
  include Mongoid::Document
  field :color, type: ColorEnum
end

class User
  include Mongoid::Document
  field :role, type: RoleEnum
end

免责声明:我没有在实际应用程序中测试它,如果不起作用,请告诉我。

英文:

First of all, there is good and bad in both MongoDB and PostgreSQL, it depends of the kind of features you need, see: https://www.geeksforgeeks.org/difference-between-postgresql-and-mongodb/

About the Phantom Custom Field Types, this is indeed doing the same stuff than ActiveRecord::Enum but asking more code to write. Could you share the not working code that you've run for your test please ?

Edit 07/02/22:

Here is an example of you could use enum in mongo without writing too much code:

module MongoEnum
  # Takes application-scope value and converts it to how it would be
  # stored in the database. Converts invalid values to nil.
  def mongoize(object)
    mapping[object]
  end

  # Get the value as it was stored in the database, and convert to
  # application-scope value. Converts invalid values to nil.
  def demongoize(object)
    inverse_mapping[object]
  end

  # Converts the object that was supplied to a criteria and converts it
  # into a query-friendly form. Returns invalid values as is.
  def evolve(object)
    mapping.fetch(object, object)
  end

  def mapping
    @mapping ||= self.const_get(:MAPPING).freeze
  end

  def inverse_mapping
    @inverse_mapping ||= mapping.invert.freeze
  end
end

class RoleEnum
  extend MongoEnum

  MAPPING = {
    'admin' => 0,
    'user' => 1,
  }.freeze
end

class ColorEnum
  extend MongoEnum

  MAPPING = {
    'black' => 0,
    'white' => 1,
  }.freeze
end

class Profile
  include Mongoid::Document
  field :color, type: ColorEnum
end

class User
  include Mongoid::Document
  field :role, type: RoleEnum
end

Disclaimer: I didn't test it in a real app, let me know if it does not work.

huangapple
  • 本文由 发表于 2023年2月7日 04:49:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75366433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定