D
D
Diesel-nick2016-11-13 13:06:14
Ruby on Rails
Diesel-nick, 2016-11-13 13:06:14

Rails 5 - how to dynamically (Ajax) add an element to a page with a has_many through association without saving it to the database?

Hello!
In Rails 5 application made 3 models:

app/models/user.rb

class User < ApplicationRecord
  has_many :team_users
  has_many :teams, through: :team_users
  accepts_nested_attributes_for :team_users, :teams, allow_destroy: true
end


app/models/team.rb
class Team < ApplicationRecord
  has_many :team_users
  has_many :users, through: :team_users
  accepts_nested_attributes_for :team_users, allow_destroy: true, reject_if: proc { |a| a['user_id'].blank? }
end


app/models/team_user.rb
class TeamUser < ApplicationRecord
  belongs_to :team
  belongs_to :user
  accepts_nested_attributes_for :team, :user, allow_destroy: true
end


app/controllers/teams_controller.rb
class TeamsController < ApplicationController
  before_action :set_team, :set_team_users, only: [:show, :edit, :update, :destroy]
  before_action :set_team_ancestry, only: [:new, :edit, :create, :update, :destroy]
  before_action :set_new_team_user, only: [:new, :edit]
  before_action :logged_in_user
  
  layout 'sidebar'
  
  # GET /teams
  def index
    @teams = Team.search(params[:search], :name).sorting(params[:sort], params[:direction]).paginate(page: params[:page])
  end

  # GET /teams/1
  def show
  end

  # GET /teams/new
  def new
    @team = Team.new(parent_id: params[:parent_id])
  end

  # GET /teams/1/edit
  def edit
    @team_users = @team.team_users
  end

  # POST /teams
  def create
    @team = Team.new(team_params)
    
    respond_to do |format|
      if @team.save
        format.html { redirect_to @team, success: t('.flash.success.message') }
      else
        format.html { render :new, danger: t('.flash.danger.message') }
      end
    end
  end

  # PATCH/PUT /teams/1
  def update
    respond_to do |format|
      if @team.update(team_params)
        format.html { redirect_to @team, success: t('.flash.success.message') }
      else
        format.html { render :edit, danger: t('.flash.danger.message') }
      end
    end
  end

  # DELETE /teams/1
  def destroy
    @team.destroy
    respond_to do |format|
      format.html { redirect_to teams_url, success: t('.flash.success.message') }
    end
  end
  
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_team
      @team = Team.find(params[:id])
    end
    
    def set_team_ancestry
      @team_collection = Team.where.not(id: params[:id]).all.each { |c| c.ancestry = c.ancestry.to_s + (c.ancestry != nil ? "/" : '') + c.id.to_s 
      }.sort{ |x,y| x.ancestry <=> y.ancestry }.map{ |c| ["-" * (c.depth - 1) + c.name,c.id] }
    end
    
    def set_team_users
      @team_users_collection = User.all.collect { |p| [ p.name, p.id ] }
    end
    
    def set_new_team_user
      @team_users_new = @team.team_users.build
    end
    
    # Never trust parameters from the scary internet, only allow the white list through.
    def team_params
      params.require(:team).permit(
        :name,
        :parent_id,
        team_users_attributes: [:_destroy, :id, :user_id]
      )
    end
end


The first time you enter the team edit page, all users associated with the team are displayed + def set_new_team_user from teams_controller.rb creates a new team_user object.

How to dynamically add users to the team page after selecting from the select and clicking on the "Add new user" button? But at the same time, the parsley for already added users should be in the form of the full name text, and to add, use the select form (i.e. Cocoon gem is not quite suitable, the parshas are the same there) and commit changes for team_users only after submitting on the main team form.

app/views/teams/edit.html.erb
cbebb328ba164488a42c52d519ca2f87.png

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question