【问题标题】:How to expose the inheritance_column in JSON如何在 JSON 中公开继承列
【发布时间】:2018-05-23 01:34:07
【问题描述】:

我需要在 JSON 响应中公开继承列,以便我可以在我的前端 (Angular) 应用程序中检索它。我怎样才能使它成为现实?

我已经搜索了很多关于这个问题的答案,但我没有找到它!

在我的情况下,我的用户可以是管理员、员工或客户。唯一的区别是 Customer 比 Admin 和 Employee 多了两个字段。这就是我决定实施 STI 的原因。如果我做出了错误的选择,请随时告诉我。

我的 user_serializer.rb 示例:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :email, :type
end

我的 user.rb 在 /models

我的 users_controllers.rb 位于 controllers/api/v1/

更新:

我的控制器:

class Api::V1::UsersController < Api::V1::BaseApiController
  before_action :authenticate_user!

  # some methods...

  def show
    user = User.find(params[:id])

    if user.present?
      render json: { data: user }, status: 200
    else
      head 404
    end
  end

  # some methods...

  private

  def user_params
    params.require(:user).permit(
      :id,
      :name,
      :email,
      :password, :password_confirmation,
      :registration,
      :cpf,
      :landline, :cellphone, :whatsapp,
      :simple_address,
      :public_agency_id,
      :public_office_id,
      :type
    )
  end
end

我的模特:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

  include DeviseTokenAuth::Concerns::User

  # belongs_to :address
  attr_accessor :skip_password_validation

  validates :name, presence: true
  validates :type, presence: true

  scope :admins, -> { where(type: 'Admin') }
  scope :employees, -> { where(type: 'Employee') }
  scope :customers, -> { where(type: 'Customer') }

  # CALLBACKS
  before_validation :generate_uuid!
  before_create :downcase_email

  def password_required?
    return false if skip_password_validation
    super
  end

  def token_validation_response
    {
      id: id,
      email: email,
      name: name,
      surname: surname,
      cpf: cpf,
      landline: landline,
      cellphone: cellphone,
      whatsapp: whatsapp,
      simple_address: simple_address,
      created_at: created_at,
      updated_at: updated_at,
      type: type
    }
  end

  private

  def generate_uuid!
    self.uid = SecureRandom.uuid if self.uid.blank?
  end

  def downcase_email
    self.email = self.email.delete(' ').downcase
  end
end

响应对象示例:

关于config/initializers/active_model_serializer.rb,我的项目中没有这个文件。

【问题讨论】:

  • 你只是使用默认的继承列'type'吗?还是您定义了一个独特的列?为什么不直接在 .jbuilder 视图输出中添加“类型”?
  • 嗨,安迪。是的,我使用的是默认的 comun :type。我从来没有使用过 jbuilder,我正在使用 gem active_model_serializers,但是它不起作用,我的 user_serializer.rb 被忽略了。
  • 你能发布你的控制器和模型吗?
  • 另外,你有config/initializers/active_model_serializer.rb吗?如果是这样,请也发布它
  • 最后,您能否输出缺少 type 字段的相关 JSON api 调用的结果?这可能有助于诊断是否使用 ActiveModelSerializer 来呈现 JSON。

标签: ruby-on-rails activerecord ruby-on-rails-5 sti


【解决方案1】:

我认为我们需要有关您的控制器、模型、初始化程序和 JSON 输出的更多信息来准确诊断此问题。但我会在黑暗中拍摄可能会有所帮助。

总体而言,您可能没有加载 UserSerializer。我建议将其移至序列化程序的根目录并在那里工作:然后,如果您出于某种原因要将其移至 api/v1,则可以专注于可能会挂起的命名空间问题。

# app/serializers/user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :email, :type
end

如果这可行,那么像 get /users/:id 这样的调用应该返回如下内容:

{ "id": 1, "name":"Bill Gates", "email":"bigcheese@microsoft.com", "type": "Employee" } 

您可能还需要更新您的应用程序控制器以进行序列化:

class ApplicationController < ActionController::API
  include ActionController::Serialization

  # ...
end

一些可能有用的资源:

  1. Codeship tutorial
  2. Building the perfect API

【讨论】:

  • 我添加了行 include ActionController::Serialization,但没有任何改变 =/
猜你喜欢
  • 2015-04-11
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多