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

时间:2017-03-13 01:29:31

标签: ruby-on-rails has-many-through

所以我在两个表has_many throughposts之间有一个users关联:

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

现在,在我的关联表(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从表单中获取user_ids(creator返回1个id,editors返回一个数组),并在创建帖子之后我删除与帖子关联的所有列,并从新属性中重新创建它们。

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

我的两个问题如下:

  1. 这是处理辅助属性的正确方法吗?
  2. 有没有办法设置关联,然后一次保存,以便进行验证?

1 个答案:

答案 0 :(得分:1)

这是一种更多的Rails方法:

使用嵌套属性

post.rb

+----+--------------------+------------+
| id | subjects_s         | address_id |
+----+--------------------+------------+
|  1 | Accounting Finance |          1 |
|  2 | Physics Math       |          2 |
+----+--------------------+------------+

assignment.rb

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

  # Your logic
end

最后,将其添加到PostsController

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

这允许您从创建发布操作创建分配,将在发布和分配上运行验证并为您运行回调。

我希望这有帮助!