Rails 7 Vanilla-Nest-Nest Gem链接添加项目不起作用

发布于 2025-01-26 22:13:55 字数 10048 浏览 3 评论 0原文

我正在尝试使用带有Rails 7的香草巢宝石,以嵌套​​编辑形式添加一个项目。该链接不起作用,也不是行动结果。

我试图在Rails 7的GEM测试路径中遵循示例代码。

这是编辑视图:

Activity/edit.html.erb

<div class="container">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <br>
        <h1 class="m-0 text-dark">Update Transaction</h1>
      </div>
    </div>
  </div>
</div>

<%= render "form", activity: @activity %>

表单部分:

active/_form.html.erb

<div class="row no-gutters">
  <div class="col-auto">
    <%= image_tag '16419114852474091540459891939039.jpeg', class: "main-image",
      width: "658", sizes: "(max-width: 767px) 96vw, (max-width: 991px) 354px, 460px", alt: ""
    %>
  </div>
  <div class="col">
    <div class="card-block px-2">
      <%= form_for activity do |form| %>
        

    <div class="row">
        <%= form.label :date_submitted, class: 'col-lg-3 text-right', style: "display: block" %>
        <div class="col-lg-2">
          <%= form.date_field :date_submitted %>
        </div>
    </div>
    <br>
    <div class="row">
      <%= form.label :transaction_date, class: 'control-label col-lg-3', style: "display: block" %>
       <div class="col-lg-2">
         <%= form.date_field :activity_date %>
       </div>
     </div>
     <br>

     <div>
       <div class="row">
         <div class="col-lg-8">
           <h3>Transaction Items</h3>
           <%= link_to_add_nested(form, :items, '#items') do %>
            <span><span> Add Item</span></span>
           <% end %>
         </div>
       </div>
        <div id='items'>
            <%= form.fields_for :items do |sub_form| %>
              <%= render 'item_fields', form: sub_form  %>
            <% end %>
        </div>
        </div>
       <div>
         <%= form.submit 'Save Update', class: "btn btn-primary" %>
       </div>
      <% end %>
      <br>

    </div>
  </div>
</div>
<div class="card-footer w-100 text-muted">
  <div>
    <%= link_to "Show this activity", @activity %> |
    <%= link_to "Back to activities", activities_path %>
  </div>
</div>

字段部分:

Activity/_item_fields.html 。

<div class="item-fields">
  <div class="row">
    <div class="col-lg-6">
      <%= form.label :amount, style: "display: block" %>
      <%= form.text_field :item_amount %>
    </div>
    <div class="col-lg-4">
      <%= form.label :vendor, style: "display: block" %>
      <%= form.text_field :vendor %>
    </div>
  </div>
  <br>
  <div class="row">
    <div class="col-lg-6">
      <%= form.label :expense_category, style: "display: block" %>
      <%= form.select(:expense_category, @category_choices) %>
    </div>
    <div class="col-lg-4">
      <%= form.label :transaction_type, style: "display: block" %>
      <%= form.select(:transaction_type, @transaction_choices) %>
    </div>
  </div>
  <br>
</div>

class Item < ApplicationRecord
  belongs_to :activity
end

class Activity < ApplicationRecord
  belongs_to :account
  belongs_to :user
  has_many :items, dependent: :destroy

  accepts_nested_attributes_for :items, reject_if: :all_blank

  has_one_attached :activity_image

  validate :acceptable_image



  def acceptable_image
    return unless activity_image.attached?

    unless activity_image.byte_size <= 5.megabyte
      errors.add(:activity_image, "is too big")
    end

    acceptable_types = ["image/jpeg", "image/png"]
    unless acceptable_types.include?(activity_image.content_type)
      errors.add(:activity_image, "must be a JPEG or PNG")
    end
  end
end

class ActivitiesController < ApplicationController
  before_action :set_activity, only: %i[ show edit update destroy add_item ]

  # GET /activities or /activities.json
  def index
    @activities = Activity.all
  end

  # GET /activities/1 or /activities/1.json
  def show
  end

  # GET /activities/new
  def new
    @activity = Activity.new
    @activity.items.build
  end

  # GET /activities/1/edit
  def edit
    set_transaction_choices
    set_category_choices
  end

  # POST /activities or /activities.json
  def create
    @activity = Activity.new(activity_params)

    respond_to do |format|
      if @activity.save
        format.html { redirect_to activity_url(@activity), notice: "Activity was successfully created." }
        format.json { render :show, status: :created, location: @activity }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @activity.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /activities/1 or /activities/1.json
  def update
    respond_to do |format|
      if @activity.update(activity_params)
        format.html { redirect_to activity_url(@activity), notice: "Activity was successfully updated." }
        format.json { render :show, status: :ok, location: @activity }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @activity.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /activities/1 or /activities/1.json
  def destroy
    @activity.destroy

    respond_to do |format|
      format.html { redirect_to activities_url, notice: "Activity was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_activity
      @activity = Activity.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def activity_params
      params.require(:activity).permit(:account_id, :user_id, :date_submitted,
        :activity_date, :reviewed, :finalized, :notes, :emailed_question,
          items_attributes: [ :id, :item_amount, :vendor,
            :expense_category, :transaction_type])
    end

    def set_transaction_choices
      @transaction_choices = [["Expense", 'expense'], ["Revenue", 'revenue']]
    end

    def set_category_choices
      @category_choices = ['Fuel', 'Tolls',
      'Repairs and Maintance', 'Plates', 'Truck Insurance',
      'Cell Phone', 'Internet', 'Satellite', 'Perdiem Days',
      'Office Supplies', 'Professional Services',
      'Other expenses', 'Liability Insurnace', 'Health Insurnace',
      'Truck Supplies and Equipment',
      'Working Clothes and Gear', 'Lease and Rental Fees',
      'Taxes and Licenses', 'Travel Expenses',
      'Contract Wages', 'Revenue',
      'Marketing Fees', 'Subscriptions',
      'Software' ]
      @category_choices.sort!
    end
end

class ItemsController < ApplicationController
  before_action :set_item, only: %i[ show edit update destroy ]

  # GET /items or /items.json
  def index
    @items = Item.all
  end

  # GET /items/1 or /items/1.json
  def show
  end

  # GET /items/new
  def new
  end

  # GET /items/1/edit
  def edit
  end


  def add_item
    @act = Activity.find(params[:activity_id])
    @act.items.create(
      activity: @act
    )
  end


  # POST /items or /items.json
  # POST /items or /items.json
  def create
    @item = Item.new(item_params)

    respond_to do |format|
      if @item.save
        format.html { redirect_to edit_activity_path(activity_id), notice: "Item was successfully created." }
        #format.json { render :show, status: :created, location: @item }
      else
        format.html { render :new, status: :unprocessable_entity }
        #format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /items/1 or /items/1.json
  def update
    respond_to do |format|
      if @item.update(item_params)
        format.html { redirect_to item_url(@item), notice: "Item was successfully updated." }
        format.json { render :show, status: :ok, location: @item }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /items/1 or /items/1.json
  def destroy
    @item.destroy

    respond_to do |format|
      format.html { redirect_to items_url, notice: "Item was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_item
      @item = Item.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def item_params
      params.require(:item).permit(:activity_id, :item_amount, :vendor, :expense_category, :transaction_type)
    end

end

import "@hotwired/turbo-rails"
import "controllers"

import "trix"
import "@rails/actiontext"

import * as bootstrap from "bootstrap"

import "custom/main"

import "vanilla-nested";

​.rb

config/importmap.rb


pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true

pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"

pin "@rails/actiontext", to: "actiontext.js"

pin "vanilla-nested", to: "vanilla_nested.js", preload: true

pin_all_from "app/javascript/custom", under: "custom"

I am trying to use the vanilla-nested gem, with Rails 7, to add an item in a nested edit form. The link is not work and not action results.

I have tried to follow the example code in the gem test path for rails 7.

Here is the edit view:

activities/edit.html.erb

<div class="container">
  <div class="container-fluid">
    <div class="row mb-2">
      <div class="col-sm-6">
        <br>
        <h1 class="m-0 text-dark">Update Transaction</h1>
      </div>
    </div>
  </div>
</div>

<%= render "form", activity: @activity %>

The form partial:

activities/_form.html.erb

<div class="row no-gutters">
  <div class="col-auto">
    <%= image_tag '16419114852474091540459891939039.jpeg', class: "main-image",
      width: "658", sizes: "(max-width: 767px) 96vw, (max-width: 991px) 354px, 460px", alt: ""
    %>
  </div>
  <div class="col">
    <div class="card-block px-2">
      <%= form_for activity do |form| %>
        

    <div class="row">
        <%= form.label :date_submitted, class: 'col-lg-3 text-right', style: "display: block" %>
        <div class="col-lg-2">
          <%= form.date_field :date_submitted %>
        </div>
    </div>
    <br>
    <div class="row">
      <%= form.label :transaction_date, class: 'control-label col-lg-3', style: "display: block" %>
       <div class="col-lg-2">
         <%= form.date_field :activity_date %>
       </div>
     </div>
     <br>

     <div>
       <div class="row">
         <div class="col-lg-8">
           <h3>Transaction Items</h3>
           <%= link_to_add_nested(form, :items, '#items') do %>
            <span><span> Add Item</span></span>
           <% end %>
         </div>
       </div>
        <div id='items'>
            <%= form.fields_for :items do |sub_form| %>
              <%= render 'item_fields', form: sub_form  %>
            <% end %>
        </div>
        </div>
       <div>
         <%= form.submit 'Save Update', class: "btn btn-primary" %>
       </div>
      <% end %>
      <br>

    </div>
  </div>
</div>
<div class="card-footer w-100 text-muted">
  <div>
    <%= link_to "Show this activity", @activity %> |
    <%= link_to "Back to activities", activities_path %>
  </div>
</div>

The fields partial:

activities/_item_fields.html.erb

<div class="item-fields">
  <div class="row">
    <div class="col-lg-6">
      <%= form.label :amount, style: "display: block" %>
      <%= form.text_field :item_amount %>
    </div>
    <div class="col-lg-4">
      <%= form.label :vendor, style: "display: block" %>
      <%= form.text_field :vendor %>
    </div>
  </div>
  <br>
  <div class="row">
    <div class="col-lg-6">
      <%= form.label :expense_category, style: "display: block" %>
      <%= form.select(:expense_category, @category_choices) %>
    </div>
    <div class="col-lg-4">
      <%= form.label :transaction_type, style: "display: block" %>
      <%= form.select(:transaction_type, @transaction_choices) %>
    </div>
  </div>
  <br>
</div>

The Items model

models/item.rb

class Item < ApplicationRecord
  belongs_to :activity
end

The Activity model:

models/activity.rb

class Activity < ApplicationRecord
  belongs_to :account
  belongs_to :user
  has_many :items, dependent: :destroy

  accepts_nested_attributes_for :items, reject_if: :all_blank

  has_one_attached :activity_image

  validate :acceptable_image



  def acceptable_image
    return unless activity_image.attached?

    unless activity_image.byte_size <= 5.megabyte
      errors.add(:activity_image, "is too big")
    end

    acceptable_types = ["image/jpeg", "image/png"]
    unless acceptable_types.include?(activity_image.content_type)
      errors.add(:activity_image, "must be a JPEG or PNG")
    end
  end
end

The Activities controller

controllers/activities_controller.rb

class ActivitiesController < ApplicationController
  before_action :set_activity, only: %i[ show edit update destroy add_item ]

  # GET /activities or /activities.json
  def index
    @activities = Activity.all
  end

  # GET /activities/1 or /activities/1.json
  def show
  end

  # GET /activities/new
  def new
    @activity = Activity.new
    @activity.items.build
  end

  # GET /activities/1/edit
  def edit
    set_transaction_choices
    set_category_choices
  end

  # POST /activities or /activities.json
  def create
    @activity = Activity.new(activity_params)

    respond_to do |format|
      if @activity.save
        format.html { redirect_to activity_url(@activity), notice: "Activity was successfully created." }
        format.json { render :show, status: :created, location: @activity }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @activity.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /activities/1 or /activities/1.json
  def update
    respond_to do |format|
      if @activity.update(activity_params)
        format.html { redirect_to activity_url(@activity), notice: "Activity was successfully updated." }
        format.json { render :show, status: :ok, location: @activity }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @activity.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /activities/1 or /activities/1.json
  def destroy
    @activity.destroy

    respond_to do |format|
      format.html { redirect_to activities_url, notice: "Activity was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_activity
      @activity = Activity.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def activity_params
      params.require(:activity).permit(:account_id, :user_id, :date_submitted,
        :activity_date, :reviewed, :finalized, :notes, :emailed_question,
          items_attributes: [ :id, :item_amount, :vendor,
            :expense_category, :transaction_type])
    end

    def set_transaction_choices
      @transaction_choices = [["Expense", 'expense'], ["Revenue", 'revenue']]
    end

    def set_category_choices
      @category_choices = ['Fuel', 'Tolls',
      'Repairs and Maintance', 'Plates', 'Truck Insurance',
      'Cell Phone', 'Internet', 'Satellite', 'Perdiem Days',
      'Office Supplies', 'Professional Services',
      'Other expenses', 'Liability Insurnace', 'Health Insurnace',
      'Truck Supplies and Equipment',
      'Working Clothes and Gear', 'Lease and Rental Fees',
      'Taxes and Licenses', 'Travel Expenses',
      'Contract Wages', 'Revenue',
      'Marketing Fees', 'Subscriptions',
      'Software' ]
      @category_choices.sort!
    end
end

The Items controller

controllers/items_controller.rb

class ItemsController < ApplicationController
  before_action :set_item, only: %i[ show edit update destroy ]

  # GET /items or /items.json
  def index
    @items = Item.all
  end

  # GET /items/1 or /items/1.json
  def show
  end

  # GET /items/new
  def new
  end

  # GET /items/1/edit
  def edit
  end


  def add_item
    @act = Activity.find(params[:activity_id])
    @act.items.create(
      activity: @act
    )
  end


  # POST /items or /items.json
  # POST /items or /items.json
  def create
    @item = Item.new(item_params)

    respond_to do |format|
      if @item.save
        format.html { redirect_to edit_activity_path(activity_id), notice: "Item was successfully created." }
        #format.json { render :show, status: :created, location: @item }
      else
        format.html { render :new, status: :unprocessable_entity }
        #format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /items/1 or /items/1.json
  def update
    respond_to do |format|
      if @item.update(item_params)
        format.html { redirect_to item_url(@item), notice: "Item was successfully updated." }
        format.json { render :show, status: :ok, location: @item }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /items/1 or /items/1.json
  def destroy
    @item.destroy

    respond_to do |format|
      format.html { redirect_to items_url, notice: "Item was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_item
      @item = Item.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def item_params
      params.require(:item).permit(:activity_id, :item_amount, :vendor, :expense_category, :transaction_type)
    end

end

The application.js file:

app/javascript/application.js

import "@hotwired/turbo-rails"
import "controllers"

import "trix"
import "@rails/actiontext"

import * as bootstrap from "bootstrap"

import "custom/main"

import "vanilla-nested";

the importmap.rb

config/importmap.rb


pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true

pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"

pin "@rails/actiontext", to: "actiontext.js"

pin "vanilla-nested", to: "vanilla_nested.js", preload: true

pin_all_from "app/javascript/custom", under: "custom"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文