【问题标题】:Assign nested attributes records to current user when using Cocoon gem使用 Cocoon gem 时将嵌套属性记录分配给当前用户
【发布时间】:2017-04-27 13:23:46
【问题描述】:

在我的应用程序中,我有模型 Post & Slides & 我有:

class Post < ActiveRecord::Base
   has_many :slides, inverse_of: :post
   accepts_nested_attributes_for :slides, reject_if: :all_blank, allow_destroy: true

一切正常,只有我需要(因为我的应用程序将如何工作),当创建 slide 时,我需要将其分配 current_user 或正在创建记录的用户。

我的slides 表中已经有user_id 并且:

class User < ActiveRecord::Base
  has_many :posts
  has_many :slide
end

class Slide < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

我的PostsController 看起来像这样:

  def new
    @post = current_user.posts.build

    // This is for adding a slide without user needing to click on link_to_add_association when they enter new page/action
    @post.slides.build
  end


  def create
    @post = current_user.posts.build(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

感谢任何帮助!

【问题讨论】:

    标签: ruby-on-rails-4 nested-attributes assign cocoon-gem


    【解决方案1】:

    有两种方法可以做到这一点:

    第一个选项:保存幻灯片时,填写用户 ID,但这很快就会变得非常混乱。您要么在before_save 的模型中执行此操作,但您如何知道当前用户 ID?或者在控制器中执行此操作并在保存之前/保存之后更改用户 ID如果未设置

    但是,还有一个更简单的选项 :) 使用 link_to_add_association (see doc) 的 :wrap_object 选项,您可以在表单中预填 user_id!就像这样:

    = link_to_add_association ('add slide', @form_obj, :slides,
          wrap_object: Proc.new {|slide| slide.user_id = current_user.id; slide })
    

    为了完全正确,您还必须按如下方式更改您的 new 方法

    @post.slides.build(user_id: current_user.id)
    

    当然,我们必须将user_id 添加到表单中,作为隐藏字段,因此它会被发送回控制器,并且不要忘记修复您的强参数子句以允许设置user_id还有:)

    【讨论】:

    • slide 位于“;”之后的目的是什么? ...它是否在|slide| 中存储了两个变量?
    • 来自文档:Note that the :wrap_object expects an object that is callable, so any Proc will do. So you could as well use it to do some fancy extra initialisation (if needed). But note you will have to return the (nested) object you want used.。所以我们接收到初始化的嵌套对象slide,用它做一些事情(设置user_id),然后返回它以便用于渲染部分(设置user_id)。
    • @nathanvda 感谢您的回答。我在link_to_add_association 和我的控制器中添加了新东西,但我收到了这个错误:undefined method "object" for nil:NilClass。我没有错吗?
    • 更多的是机制...我可以在第一部分看到作业,但是 ;把我扔了,因为通常我只在 C 等其他语言中看到它
    • @Mirv ; 与 c 中的完全一样,所以它允许我写一行:) stackoverflow.com/questions/3953846/…
    【解决方案2】:

    当我看到这个时,我看到了三种解决方法,但由于你已经在茧上,我会放弃用户和幻灯片之间的连接 - 因为它有点违反良好的数据库实践(直到你点击您的页面如此受欢迎,您当然必须对其进行优化,但这会有所不同)。

    你正在使用茧,但你还没有完全利用关系的嵌套......

    最好的做法是让 cocoon 的嵌套同时创建 & 而不是尝试分配给 current_user 你这样称呼:

    @slides = current_user.posts.find_first(param[:id]).slides
    

    @slides 保存所有结果,.Post.find(param[:id]) 查找current_user 的特定帖子。

    注意:这不是最优化的方式,我还没有测试过,但它向您展示了您可以考虑关系的一种方式的格式。您需要点击 rails console 并运行一些测试,例如 ...

     (rails console)> @user = User.first
    

    接下来我们测试是否有可用的帖子,因为测试空白而没有得到结果令人沮丧...

    (rails console)> @posts = @user.posts 
    

    然后我们使用find 方法,我将使用Post.first 只是为了获得一个工作ID,您可以轻松输入“1”或任何您知道有效的数字...

    (rails console)> @post = @posts.find(Post.first)
    

    最后,我们使用所有幻灯片来确保它是有效的数据集

    (rails console)> @post.slides
    

    如果您稍后想要特定幻灯片并具有has_many 关系,只需在.slides 之后标记find 方法即可。

    还有最后一件事 - 当您在前面声明需要关联 current_user 时,您可以使用 model.rb 中的条目来创建方法或范围来获取数据并允许您将其链接到current_user 更容易,甚至可以使用 .where 方法删除一些定向 SQL 查询,以便在性能存在问题时提取该信息。


    我在那里发现了第二个优化...如果一切正常 - 不用担心这个!

    不要忘记 strong_parameters 嵌套来完全做到这一点......Strong Param white listing

    Basic format ... `.permit(:id, :something, slide_attributes: [:id, :name, :whatever, :_destroy])
    

    【讨论】:

    • 我认为Slide 中有一个user_id,因为帖子的创建者可能与幻灯片的创建者不同。代码current_user.Post.find ... 也不起作用。应该是current_user.posts.find_first(id:...).slidescurrent_user.post.slides.build 也是错误的:需要两个连续的构建(首先你在关联上构建一个新帖子——所以用户 ID 设置正确,然后你构建一个幻灯片,所以帖子 ID 将正确设置, 一起保存时)
    • 已编辑的第二部分 - 第一部分是因为 find() 方法将返回找到的所有条目?
    • 另外,我会留下 params[:id] 还是放弃它?
    • 还是错了,你写current_user.Post current_user.posts 确实如此,然后在该关联上,您可以使用给定的id 搜索帖子(我们要查找的ID 确实是params[:id]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    相关资源
    最近更新 更多