0

I'm trying to allow users to create projects...and as soon as a user creates a project...they will automatically be following that project. (I have my app setup to allow a user to follow a project from a 'follow' button on the project profile). I would like the project creator to automatically be following the new project without having to click the 'follow' button. I rearranged my code as per Bilal's answer...but now clicking 'create project' simply refreshes the 'new' view (no project gets posted). I assumed this has to do with the Pundit authorizations but perhaps someone can clarify why the 'create' action is no longer working...

My Projects Model:

class Project < ActiveRecord::Base
  belongs_to :owner, :foreign_key=>'user_id', :class_name=>'User'

  has_many :reverse_relationships, foreign_key: "followed_id",
                                   class_name: "Relationship",
                                   dependent: :destroy
  has_many :followers, through: :reverse_relationships, source: :follower

  validates :title, presence: true
  validates :background, presence: true
  validates :projectimage, presence: true

  mount_uploader :projectimage, ProjectimageUploader
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
  after_update :crop_projectimage

  def crop_projectimage
    projectimage.recreate_versions! if crop_x.present?
  end

  def private?
    self.is_private == true
  end

  def public?
    self.is_private == false
  end
end

Relationships Model:

class Relationship < ActiveRecord::Base
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "Project"
  validates :follower_id, presence: true
  validates :followed_id, presence: true

  enum role: [:admin, :collaborator, :visitor]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :visitor
  end
end

My Projects Controller:

class ProjectsController < ApplicationController
  before_filter :authenticate_user!, only: [:create, :new, :edit, :update, :delete, :followers]

  # CREATES REDIRECT & ALERT MESSAGE WHEN PUNDIT SEES SOMEONE IS NOT AUTHORIZED (via :not_authorized_in_project below)
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  def new
    @project = Project.new
  end

  def show
    @project = Project.find(params[:id])
    authorize @project, :visit? 
    # @user = User.where(:id => @project.user_id).first
  rescue Pundit::NotAuthorizedError
    flash[:warning] = "You are not authorized to access this page."
    redirect_to project_path || root_path
  end

  def index
    @projects = policy_scope(Project).all
  end

  def create
    @project = current_user.own_projects.build(project_params)
    @project.followers << current_user
    if @project.save
      if params[:project][:projectimage].present?
        render :crop
      else
        flash[:success] = "You've successfully created a Project..."
        redirect_to @project
      end
    else
      render 'new'
    end
  end

  def update
    @project = Project.find(params[:id])
    if @project.update_attributes(project_params)
      if params[:project][:projectimage].present?
        render :crop
      else
        flash[:success] = "Project Created"
        redirect_to @project
      end
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "Project destroyed"
    redirect_to users_path
  end

  def followers
    @title = "Following this Project"
    @project = Project.find(params[:id])
    @project = @project.followers.paginate(page: params[:page])
    render 'show_follow_project'
  end

  private

  def project_params
    params.require(:project).permit(:title, :background, :is_private, :projectimage, :user_id, :crop_x, :crop_y, :crop_w, :crop_h)
  end

  def user_not_authorized
    flash[:warning] = "You are not authorized to access this page."
    redirect_to project_path(@project) || root_path
  end
end

My User Model:

class User < ActiveRecord::Base
  has_many :own_projects, :class_name=>'Project'

  has_many :projects
  has_many :relationships, foreign_key: "follower_id", dependent: :destroy

  has_many :followed_projects, through: :relationships, source: :followed
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  def following?(some_project)
   relationships.find_by_followed_id(some_project.id)
  end

  def follow!(some_project)
   self.relationships.create!(followed_id: some_project.id)
  end

  def unfollow!(some_project)
   relationships.find_by_followed_id(some_project.id).destroy
  end

Pundit Project Policy:

class ProjectPolicy < Struct.new(:user, :project)
  class Scope < Struct.new(:user, :scope)
    # SCOPE & RESOLVE METHOD USED TO RESTRICT PROJECTS INDEX TO PUBLIC & THOSE YOU'RE AN ADMIN/COLLAB ON
    def resolve
      followed_project_ids = user.followed_projects.map(&:id)
      public_project_ids = Project.where(:is_private=>false).map(&:id)
      Project.where(:id=>followed_project_ids + public_project_ids)
    end
  end

    def update?
      user.project_admin? || user.project_collaborator?
    end


    # METHOD USED IN PROJECTS_CONTROLLER (SHOW) TO RESTRICT VISITING PRIVATE PROJECT PROFILES TO ADMINS & COLLABS
    def visit?
      user.project_admin?(project) || user.project_collaborator?(project)
    end

end
BB500
  • 549
  • 2
  • 6
  • 24
  • 1
    Try cutting down to the chase when posting questions. This amount of code is completely unnecesary (there's no need to post the WHOLE controller/model). – Waclock Mar 20 '16 at 21:15
  • 1
    hah sorry man - will do in the future. in past posts, I would get responses to post more code so I figured it was better to have too much rather than too little. (when you're a beginner, you're not sure where you might be going wrong sometimes) – BB500 Mar 20 '16 at 21:24

1 Answers1

1

It's never a good idea to use current_user in a model, see this for reference.

Any easy and efficient place to set this thing would be the controller itself. So, you can write the following code:

def create
  @project = current_user.own_projects.build(project_params)
  @project.followers << current_user
  if @project.save
    if params[:project][:projectimage].present?
      render :crop
    else
      flash[:success] = "You've successfully created a Project..."
      redirect_to @project
    end
  else
    render 'new'
  end
end
Community
  • 1
  • 1
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
  • Thank Bilal - but this adding this (and removing the after_create and method from the model) is causing an issue now creating the project. It simply refreshes the 'new' project view and nothing gets created. I'm thinking this is maybe because of my pundit authorizations? – BB500 Mar 20 '16 at 20:53
  • I've added my application_policy and project policy from the pundit gem...any idea what could be causing the issue? thx – BB500 Mar 20 '16 at 20:58
  • @BB500 For that, you could ask another question regarding `pundit` gem. – Arslan Ali Mar 21 '16 at 06:18