Rails 上的 Ruby - Cocoon gem,不要在编辑操作中预先填充 existing/added 个帖子

Ruby on Rails - Cocoon gem, Don't Pre-populate existing/added posts in edit action

我的应用程序有模型 CampaignPost,我有:

class Campaign < ActiveRecord::Base
  has_many :posts, inverse_of: :campaign
  accepts_nested_attributes_for :posts, reject_if: :all_blank, allow_destroy: true

class Post < ActiveRecord::Base
  belongs_to :campaign

我的表格:

= simple_form_for(@campaign) do |f|
  = f.error_notification
  = f.input :title
  #posts
    = f.simple_fields_for :posts do |post|
      = render 'post_fields', f: post
    .links
      = link_to_add_association 'Add Post', f, :posts, wrap_object: Proc.new {|post| post.user_id = current_user.id; post }

我用 Cocoon gem 代替 nested_forms

当我转到 campaigns#edit 视图时,我可以看到所有 posts 已经添加到 campaign ([=63 的自然行为=]),我可以向我的活动添加新帖子 and/or 编辑现有 posts .

我还有一个按钮有这个 param: add_to: 'existing_campaign' 我想要实现的是,如果我的 link 有 ?add_to=existing_campaign,我不想 show/Pre-populate 任何已经添加到 campaignposts,所以用户只能添加新的 postscampaign

我的 link_to 看起来像: = link_to 'Add Post', edit_campaign_path(campaign, add_to: 'existing_campaign'),

简短说明:如果编辑 link 有参数 ?add_to=existing_campaign,我不会预填充已经添加的 posts,如果参数不存在,我预填充 posts

我怎样才能做到这一点?

更新更多细节...

作为设计者,您需要决定是否要将逻辑移至助手。如果您不知道瘦控制器/胖模型或组织代码库的其他策略,请阅读此... Link。现在,我假设您将使用助手。

理论和一些挑剔的东西 ...

瘦控制器将要发生的事情是您需要在视图逻辑中访问该参数(但这将是不安全的并且违反了 rails 方式)。由于您不应该只向视图公开参数,而是传递包含参数值的消息。面向对象教会我们使用传递消息。 Rails 表示在控制器中使用实例变量 (@something) 并且视图可以访问这些变量。

接下来我们需要设置条件逻辑。 Rails 方法之一是使用助手从视图中删除无关的逻辑或使其可读。除非您有其他我不知道的原因,否则这符合条件-这应该在帮手中。我很想在这里只测试布尔值并为您创建的额外视图调用另一个部分。

这意味着我必须假设您的测试也会发生变化(如果不是以标准方式完成,您必须包含才能访问该 method/object)。


具体到你的问题

  1. link_to调用嵌套表单的页面应该是true/false...

= link_to 'Add Post', edit_campaign_path(campaign, show_posts: false)

  1. 您的控制器将 @show_posts 用于您正在使用的广告系列控制器的任何操作(通常是编辑或新建)。您需要设置 @show_posts = params[:show_posts]
  2. 编写助手...
helpers/campaign_helper.rb

def showPosts?(show_posts)
  testPart == true ? 'only_comment' : 'post_fields'  
end
  1. 一个新的部分...基本相同,但删除了填充其他帖子的 simple_fields_for 循环。
  2. 您的 _form 部分将从上面的内容变为 ...
= f.simple_fields_for :posts do |post|
  = render 'posts_fields', f: post

至...

...
#posts
  = render showPosts?(@show_posts), f: post
...

更新,我测试了所有部分并让它与您的确切语法一起工作 - 我最终在助手中使用了三元运算符。

在活动中设置 attr_accessor 以控制是否应查看现有帖子...

class Campaign < ActiveRecord::Base
  attr_accessor hide_posts
  ...
end

在您的 edit 方法中设置值

class CampaignsController < ApplicationController

  def edit
    @campaign.hide_posts = params[:add_to] == 'existing_campaign'
    ...
  end

确保临时变量在你的强参数中(以便更新失败后重新显示记得隐藏帖子)

def campaign_params
  params.require(:campaign).permit( :hide_posts, ...

现在在你看来你可以做...

= f.hidden_field :hide_posts
= f.simple_fields_for :posts do |post|
  = render('post_fields', f: post) unless @campaign.hide_posts && post.object.persisted?