使用 Cocoon 时将嵌套属性记录分配给当前用户 gem

Assign nested attributes records to current user when using Cocoon gem

在我的应用程序中,我有模型 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 table 中已经有 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

感谢任何帮助!

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

您正在使用 cocoon,但您还没有充分利用关系的嵌套...

最好的做法是让 cocoon 的嵌套同时创建 & 而不是尝试分配给 current_user 你调用类似的东西:

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

@slides保存所有结果,.Post.find(param[:id])current_user找到一个特定的post。

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

 (rails console)> @user = User.first

接下来我们测试是否有 post 可用,因为测试空白却得不到结果是令人沮丧的...

(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 中的条目来创建方法或范围来获取数据并允许您更轻松地 link 它到 current_user 甚至可以使用 .where 方法删除一些定向 SQL 查询,以便在性能有问题时提取该信息。


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

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

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

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

第一个选项:保存幻灯片时,填写用户ID,但这很快就会变得很乱。您要么在 before_save 的模型中执行此操作,但您如何知道当前用户 ID?或者在控制器中执行此操作并更改用户 ID if not set before saving/after saving.

不过,还有一个更简单的选择:) 使用 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 还有 :)