Ask A Question

Notifications

You’re not receiving notifications from this thread.

How can I subscribe a user when creating a new project?

Lauro asked in Ruby

How can I subscribe a user when creating a new project?

I'm having a hard time on the create method. Currently this is my code:

Projects controller

  def create
    @project = Project.new(project_params)

    @project = Project.find(params[:project_id])
    current_user.subscriptions.create(project: project)

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

Project Model

class Project < ApplicationRecord

  has_many :subscriptions
    has_many :users, through: :subscriptions

end

User Model

class User < ApplicationRecord

  has_many :subscriptions
  has_many :projects, through: :subscriptions

end
Reply

Couple things I notice off the bat:

  1. You can't look up the project until it's actually been created so there is a database ID.
  2. You can't create the subscription just yet either since the project hasn't been saved yet.

Here's what I would do:

 def create
    @project = Project.new(project_params)
        @project.subscriptions.new(user: current_user)

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

This is going to build the project in memory first. Then it creates an associated Subscription record in memory as well, but inside the project. Since the two are associated in memory, this will make sure that when you save the @project the subscription also gets saved and both will get inserted into the database as long as the validations pass.

Reply

Thanks Chris! It worked. :grinning: :raised_hands: Your explanation helped a lot.

I still need to work on understanding the logic for associations.

Reply

Chris! How can I hide a project when a user is not subscribed to a project?

Reply

If you are using Devise you can call usersignedin? to determine if a user is or not logged in.

<% if user_signed_in? %>
    Code to display when the user is signed in
<% else %>
    Code to display when the user is not signed in
<% end %>
Reply

Thanks Jack and Steve! After a couple of days, this code seeme to do the thick. But it seems abit smelly. What do you guys think? Can this be improved?

  def show
     begin
       @project = current_user.projects
         .joins(:subscriptions)
         .where(subscriptions: {user_id: current_user.id})
         .find(params[:id])
     rescue ActiveRecord::RecordNotFound => e
       redirect_to root_path, notice: 'No estas subscrito'
     end
   end
Reply

I think you should be able to simply do the following instead:

@projects = current_user.projects.find(params[:id])

The trick here is that Rails knows how to do the join and where automatically because the relationship is defined as "has_many through". The has_many means it knows it must join, and through means that it needs to join twice.

Your query should work, but you're basically redefining exactly what Rails is doing internally so you can get rid of the join and where and it should produce the same output. :)

Reply

Wow! Thanks for taking the time to answer. Always so helpful Chris! :grinning:

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 86,946+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.