Добавить проект при загрузке CSV - PullRequest
1 голос
/ 11 октября 2019

Привет, у меня есть приложение, в котором есть модели проектов и предметов.

Предмет принадлежит проекту.

Я массово импортирую элементы через импорт CSV.

На данный момент @project идентифицируется и вызывается в хэше, используя столбец в CSV.

Я хочу изменить это, чтобы иметь возможность удалить столбец в csv и использовать ассоциацию при вызове импорта csv со страницы @project

app / models / project.rb

class Project < ApplicationRecord

    has_many :items, dependent: :destroy

end

app / models / item.rb

class Item < ApplicationRecord
  belongs_to :project

  enum status: [:unscheduled, :scheduled, :delivered]

  def self.import(file)
    CSV.foreach(file.path, headers: true, header_converters: :symbol) do |row|
      Item.create! row.to_hash
    end
  end

  def self.to_csv
    CSV.generate do |csv|
        csv << column_names
        all.each do |item|
            csv << item.attributes.values_at(*column_names)
        end
    end
  end
end

элемент вложен в проект

app/controllers/projects_controller.rb

class ProjectsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_project, only: [:show, :edit, :update, :destroy]


  # GET /projects
  # GET /projects.json
  def index
    @projects = current_user.projects.all
  end

  # GET /projects/1
  # GET /projects/1.json
  def show
    @project = Project.find(params[:id])
    @item = @project.items.new
    @items = if params[:term]
      @project.items.where('name LIKE ?', "%#{params[:term]}%")
    else
      @project.items.all
    end
    respond_to do |format|
      format.html
      format.csv { send_data @items.to_csv }
    end
  end

  # GET /projects/new
  def new
    @project = Project.new
  end

  # GET /projects/1/edit
  def edit
  end

  # POST /projects
  # POST /projects.json
  def create
    @project = Project.new(project_params)
    @project.project_users.new(user:current_user, role: "owner")

    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

  # PATCH/PUT /projects/1
  # PATCH/PUT /projects/1.json
  def update
    respond_to do |format|
      if @project.update(project_params)
        format.html { redirect_to @project, notice: 'Project was successfully updated.' }
        format.json { render :show, status: :ok, location: @project }
      else
        format.html { render :edit }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /projects/1
  # DELETE /projects/1.json
  def destroy
    @project.destroy
    respond_to do |format|
      format.html { redirect_to projects_url, notice: 'Project was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_project
      @project = current_user.projects.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def project_params
      params.require(:project).permit(:name, :number, :street, :suburb, :state, :postcode, :country)
    end
end

app / controllers / projects / items_controller.rb

class Projects::ItemsController < ApplicationController

  # GET /items/new
  def new
    @project = Project.find(params[:project_id])
    @item = Item.new
  end

  def index
    @project = Project.find(params[:project_id])
    @items = @project.items.all
    respond_to do |format|
      format.html
      format.csv { send_data @items.to_csv }
    end
  end
  # GET /items/1/edit
  def edit
  end

  # POST /items
  # POST /items.json
  def create
    @project = Project.find(params[:project_id])
    @item = Item.new(item_params)
    @item.project_id = @project.id
    respond_to do |format|
      if @item.save
        format.html { redirect_to @item.project, notice: 'Item was successfully created.' }
        format.json { render :show, status: :created, location: @item.project }
      else
        format.html { render :new }
        format.json { render json: @item.project.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /items/1
  # PATCH/PUT /items/1.json
  def update
    @item = Item.find(params[:id])
    @project = Project.find(params[:project_id])
    respond_to do |format|
      if @item.update(item_params)
        format.html { redirect_to @item.project, notice: 'Item was successfully updated.' }
        format.json { render :show, status: :ok, location: @item.project }
      else
        format.html { render :edit }
        format.json { render json: @item.project.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /items/1
  # DELETE /items/1.json
  def destroy
    @item = Item.find(params[:id])
    @project = Project.find(params[:project_id])
    title = @item.model
    if @item.destroy
      flash[:notice] = "One \'#{title}' was successfully destroyed."
      redirect_to @project 
    else
      flash[:notice] = "Error Yo"
      render :show
    end
  end

  def import
    Item.import(params[:file])
    redirect_to projects_path(@project), notice: "Sucessfully Added Items"
   end

  private
    # Use callbacks to share common setup or constraints between actions.

    # Never trust parameters from the scary internet, only allow the white list through.
    def item_params
      params.require(:item).permit(:model, :project_id, :name, :search)
    end
end

Вы заметите, что у меня есть импорт CSV, который отлично работает, если файл загрузки содержит идентификатор проекта.

item.csv

model   project_id  name
A          8         1

app /views / projects / show.html.erb

<%= form_tag import_project_items_path(@project) , multipart: true do%>
          <div class="custom-file">
            <%= file_field_tag :file, placeholder: 'Add Your File', required: true, class: 'custom-file-input', id: 'customFile' %>
            <label class="custom-file-label" for="customFile">Choose file</label>
          </div>
          <div class="form-group mt-2">
            <%= submit_tag "Upload Items", class: 'btn btn-primary btn-block' %>
          </div>
          <% end %>

Поэтому мой вопрос заключается в том, как добавить @project к импорту элемента проекта

   def import
        Item.import(params[:file])
        redirect_to projects_path(@project), notice: "Sucessfully Added Items"
       end

def self.import(file)
    CSV.foreach(file.path, headers: true, header_converters: :symbol) do |row|
      Item.create! row.to_hash
    end
  end

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Процесс написания моего кода выше помог мне понять.

Мне просто пришлось изменить одну строку в моем импорте

с

def import
 Item.import(params[:file])
 redirect_to projects_path(@project), notice: "Sucessfully Added Items"
end

на

def import
 @project = Project.find(params[:project_id])
 @project.items.import(params[:file])
 redirect_to projects_path(@project), notice: "Sucessfully Imported Items!"
end
0 голосов
/ 11 октября 2019

Вы должны создать путь в маршрутах .rb

get 'projects/:project_id/items/:id/import' => 'items#import', as: :items_import

, а затем из любого места (например, со страницы шоу) вы можете просто позвонить

items_import_path(@project, @item)
...