has_many:通过4r帖子贡献

时间:2015-10-30 17:22:26

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

我在理解如何在视图中设置贡献控制器和表单方面遇到了一些麻烦。我在视图中设置了一些表单,所以我知道连接表有效。

截至目前,帖子属于用户&&用户has_many帖子

目的:
1. user1创建post - 属于user1
2. user2请求加入user1_post作为贡献者
3. user1接受或拒绝请求
4. user2现在是user1_post的贡献者
5. user1可以删除user2作为贡献者

得到了has_many:通过正确设置并在控制台中测试了它

contribution.rb

class Contribution < ActiveRecord::Base
  belongs_to :post
  belongs_to :user

  def accept
    self.accepted = true
  end
end

post.rb

class Post < ActiveRecord::Base
  belongs_to :author, class_name: 'User'
  has_many :contribution_requests, -> { where(accepted: false) }, class_name: 'Contribution'
  has_many :contributions, -> { where(accepted: true) }
  has_many :contributors, through: :contributions, source: :user
end

user.rb

class User < ActiveRecord::Base
  has_many :posts, foreign_key: 'author_id'
  has_many :contribution_requests, -> { where(accepted: false) }, class_name: 'Contribution'
  has_many :contributions, -> { where(accepted: true) }
  has_many :contributed_posts, through: :contributions, source: :post
end

contributions_controller.rb

class ContributionsController < ApplicationController
  def create
    @contribution = current_user.contributions.build(:user_id => params[:id])
    if @contribution.save
        flash[:notice] = "Added contributor."
        redirect_to posts_path(@post)
    else
        flash[:error] = "Unable to add contributor."
        redirect_to posts_path(@post)
    end
  end

  def destroy
    @contribution = current_user.contributions.find(params[:id])
    @contribution.destroy
        flash[:notice] = "Removed contributor."
        redirect_to root_url
    end
end

1 个答案:

答案 0 :(得分:1)

没有太多背景,这就是我要做的事情:

#config/routes.rb
resources :posts do
   resources :contributions, only: [:create, :destroy] #-> can use posts#edit to add extra contributions
end

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
   def edit
      @post = Post.find params[:id]
   end
end

#app/views/contributions/edit.html.erb
<%= form_for @post do |f| %>
    # @post form 
<% end %>
## contributor add / remove form (select boxes) 

#app/controllers/contributions_controller.rb
class ContributionsController < ApplicationController
   def create
      @post = Post.find params[:post_id]
      @contribution = current_user.contributions.new contribution_params
      @contribution.post = @post

      notice = @contribution.save ? "Added Contributor" : "Unable to add contributor"
      redirect_to @post, notice: notice
   end

   def destroy
      @contribution = current_user.contributions.find params[:id]
      @contribution.destroy

      redirect_to root_url, notice: "Removed Contributor"
end

   private

   def contribution_params 
      params.require(:contribution).permit(:user, :post, :accepted)
   end
end

顺便说一句,您应该查看ActiveRecordExtension,为您的conbtributions关联提供一些方法(而不是多个关联):

#app/models/post.rb
class Post < ActiveRecord::Base
   has_many :contributions, -> { extending ContributionExtension }
end

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :contributions, -> { extending ContributionExtension }
end

#app/models/concerns/contribution_extension.rb
class ContributionExtension
   def requests(status=false)
     where accepted: status
   end

   def accepted(status=true)
     where accepted: status
   end
end

@post.contirbutions.requets
@post.contributions.accepted

@user.contributions.requests
@user.contributions.accepted

-

此外,您应该考虑为Contribution模型实施state_machine

#app/models/contribution.rb
class Contribution < ActiveRecord::Base
   state_machine :accepted, initial: :pending do
      event :accept do
         transition [:pending, :denied] => :accepted
      end

      event :deny do
         transition [:pending, :accepted] => :denied
      end
   end
end

很棒article about it here

这将允许您致电:

@contribution = current_user.contributions.find params[:id]
@contribution.accept

它还会为您提供其他几种很酷的方法:

@contribution.accepted?
@contribution.state