【问题标题】:Rendering json from two models in Rails index从 Rails 索引中的两个模型渲染 json
【发布时间】:2014-08-13 13:13:06
【问题描述】:

我想在索引方法中呈现 json,该方法连接来自 Rails 中的外键相关表的数据。我有一个以 user_id 作为外键的模型。

class Batch < ActiveRecord::Base
  belongs_to :user

然后我将呈现该表并公开 user_id 字段。

def index
    panels = Batch.where("user_id = #{current_user.id} or (user_id <> #{current_user.id} and public_panel = true)")
    render json: panels,  only: [:id, :description, :name, :public_panel, :updated_at, :user_id], root: false
end

我想做的是以某种方式公开用户名,该用户名位于 Users 模型上。即:user_id.user_name

编辑

通过阅读文档,我认为我需要使用 include 但也想为其中一个字段设置别名。我在两个表中都有一个名为 name 的字段。

这个 include 有问题

  def index
    panels = Batch.include([:users]).where("user_id = #{current_user.id} or (user_id <> #{current_user.id} and public_panel = true)")
    render json: panels,  only: [:id, :name, :description, :public_panel, :updated_at, :user_id], root: false
  end

EDIT2

谢谢@Paritosh Piplewar ...我在语法上遇到了一些错误。更复杂的是,我所关注的字段是 user.name,而不是 user.user_name。这会和 batches.name 冲突,所以我需要给它起别名。

Started GET "/api/batches" for 10.0.2.2 at 2014-08-13 15:39:03 +0200

SyntaxError (/home/assay/assay/app/controllers/api/batches_controller.rb:11: syntax error, unexpected tLABEL
              user: { only: :first_name }, 
                   ^
/home/assay/assay/app/controllers/api/batches_controller.rb:11: syntax error, unexpected ',', expecting keyword_end
              user: { only: :first_name }, 
                                          ^
/home/assay/assay/app/controllers/api/batches_controller.rb:12: syntax error, unexpected ',', expecting keyword_end):

编辑 3

原来的问题已经回答了,但是返回的json是这样的

data: [{"id"=>1306, "updated_at"=>Wed, 13 Aug 2014 12:37:23 UTC +00:00, "description"=>"asc", "user_id"=>1, "public_panel"=>true, "user"=>{"name"=>"Joe Bloggs"}}, {"id"=>1307, 

这一点导致我的 Angular.js 前端出现问题。

"user"=>{"name"=>"Joe Bloggs"}}

【问题讨论】:

  • 您可以在批处理模型中委托用户名
  • 谢谢@AnilMaurya 我该怎么做?
  • 旁注:在数据库查询中使用字符串插值可能非常不安全。而是使用 ? 替换来正确引用您的值以防止 SQL 注入,如下所示:where("user_id = ? or (user_id &lt;&gt; ? and public_panel = true)", current_user.id, current_user.id)

标签: ruby-on-rails


【解决方案1】:

我假设你的意思是user.user_name

你可以这样做

def index
    panels = Batch.where("user_id = #{current_user.id} or (user_id <> #{current_user.id} and public_panel = true)")
    data = panels.as_json(include: 
                {user: { only: :name }}, 
                only: [:id, :description, :public_panel, :updated_at, :user_id],
                root: false) 
    render json: data
end

【讨论】:

  • 现在试一试。只是简单的hash 事情
  • 有点工作,我想原来的问题已经回答了。见编辑 3。
【解决方案2】:

您可以定义自定义方法并执行此操作。像这样的

class Batch < ActiveRecord::Base
  belongs_to :user

  def user_name
    user.name
  end

end

现在,在控制器中你可以简单地做到这一点

def index
    panels = Batch.where("user_id = ? or (user_id <> ? and public_panel = true)", current_user.id, current_user.id)
    data = panels.as_json(methods: :user_name, 
                only: [:id, :description, :public_panel, :updated_at, :user_id, :user_name],
                root: false) 
    render json: data
end

【讨论】:

  • 完美,谢谢。我不得不做一个小改动:panels.as_json 中的 root: false 被忽略了......所以我删除了它并添加了 render json: data, root: false 并且它工作正常。
  • 太棒了。确保n+1 查询。如果有,您可能需要preload 它。此外,如果您认为遗漏了什么,请随时相应地更新此答案。我没有尝试过,只是按照文档编写的,所以可能会有一些愚蠢的错误。谢谢。
【解决方案3】:

对于更复杂的 json 视图,而不仅仅是重新渲染单个模型,我会告诉你使用 jbuilder。 Jbuilder 现在是 rails 框架的一部分。

就这么简单

  1. 删除渲染线并使面板成为实例变量 (@panels)
  2. 在 app/views/api/batches 下创建 index.json.jbuilder 文件
  3. 创建您想要的视图
json.array @panels do |panel|
    panel.(panel, 
      :id, 
      :description, 
      :public_panel, 
      :user_id, 
      :updated_at
    )

    json.user panel.user.user_name
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 2012-03-03
    • 2018-03-27
    • 2010-11-18
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多