Rails 有很多通过关联设置多个属性

Rails has many through association setting multiple attributes

所以我有一个 has_many through 关联,其中两个 tables postsusers:

class Post < ApplicationRecord
  has_many :assignments
  has_many :users, :through => :assignments
end 

class User < ApplicationRecord
  has_many :assignments
  has_many :posts, :through => :assignments
end 

class Assignment < ApplicationRecord
  belongs_to :request
  belongs_to :user
end

现在在我的协会 table (assignment) 中有 creator:booleaneditor:boolean 的附加属性。

我的问题是从控制器内部设置这些次要属性的最佳方式是什么?

环顾四周,我找到了当前的解决方案:

posts_controller.rb:

class PostsController < ApplicationController
  def create
    params.permit!
    @post = Post.new(post_params)

    if @post.save    
      Assignment.handle_post(@post.id, params[:creator], params[:editors])
      redirect_to posts_path, notice: "The post #{@post.title} has been created."
    else
      render "new"
    end
end 

assignment.rb:

class Assignment < ApplicationRecord
  belongs_to :request
  belongs_to :user

  def self.handle_post(post_id, creator, assignment)
    Assignment.where(:post_id => post_id).delete_all

    Assignment.create!(:post_id => post_id, :user_id => creator, :creator => true, :editor => false)

    if editors.present?
      editors.each do |e| 
        Assignment.create!(:post_id => post_id, :user_id => e, :creator => false, :editor => true)
      end
    end
  end
end

所以实际上发生的事情是我通过 params (creator returns 1 id, editors returns 一个数组),在创建 post 之后,我将删除与 post 关联的所有列,并根据新属性重新创建它们。

我遇到的问题是我无法 运行 post 对这些关联进行验证(例如检查创建者是否存在)。

我的两个问题如下:

  1. 这是处理次要属性的正确方法吗?
  2. 有没有一种方法可以设置关联然后一次性保存所有关联以便执行验证?

这是一种更 Rails 的方法:

使用嵌套属性

post.rb

class Post < ApplicationRecord
  # Associations
  has_many :assignments, inverse_of: :post
  has_many :users, through: :assignments
  accepts_nested_attributes_for :assignments

  # Your logic
end

assignment.rb

class Assignment < ApplicationRecord
  after_create :set_editors

  belongs_to :request
  belongs_to :user
  belongs_to :post, inverse_of: :assignments

  # I would create attribute accessors to handle the values passed to the model
  attr_accessor :editors

  # Your validations go here
  validates :user_id, presence: true

  # Your logic

  private

  def set_editors
    # you can perform deeper vaidation here for the editors attribute
    if editors.present?
      editors.each do |e|
        Assignment.create!(post_id: post_id, user_id: e, creator: false, editor: true)
      end
    end
  end
end

最后,将其添加到您的 PostsController

params.require(:post).permit(..., assignments_attributes: [...])

这允许您从创建 Post 操作创建作业,运行 验证 Post 和作业以及 运行 回调。

希望对您有所帮助!