【问题标题】:How to fill multiple form fields using attribute from another model?如何使用另一个模型的属性填充多个表单字段?
【发布时间】:2016-04-10 16:12:57
【问题描述】:

我有 3 个模型 - User、Shipment 和 Friendship。用户可以通过友谊模型与另一个用户成为朋友。用户还可以创建货件,并可以向其添加朋友用户。 User 和 Shipment 模型中有地址属性。我需要让用户可以在同一表格中以两种方式填写该地址字段:

  1. 通过手动填写地址字段。
  2. 通过从选择列表中选择该用户的朋友 - 所以朋友 address-attribute 传输并填写 Shipments adress-attribute (如 ctrl-c/ctrl-v)并且用户可以提交表单。

我可以猜到,需要 AJAX 来刷新内容而不刷新页面。

发货型号:

class Shipment < ActiveRecord::Base
  belongs_to :user
  belongs_to :friendship

  validates :image, presence: true
  validates :user_id, presence: true
end

发货管理员:

class ShipmentsController < ApplicationController

  helper_method :shipment, :user
  before_action :set_shipment, only: [:show]
  before_action :authenticate_user!
  before_action :require_same_user, only: [:show]

  def index
    @shipments = Shipment.all
  end

  def new
    @shipment = Shipment.new
  end

  def create
    @shipment = Shipment.new(shipment_params)
    @shipment.user = current_user
    if @shipment.save
      flash[:success] = "Shipment etc."
      redirect_to shipment_path(@shipment)
    else
      render 'new'
    end
  end

  def show
    @shipment = Shipment.find(params[:id])
  end

  private

    def user
      @user = current_user
    end

    def shipment
      @shipment = user.shipments.new
    end

    def shipment_params
      params.require(:shipment).permit(:name, :kg, :length, :width, :height,
                                       :adress, :image, :user_id, :friend_id)
    end

    def set_shipment
      @shipment = Shipment.find(params[:id])
    end

    def require_same_user
      if current_user != @shipment.user
        flash[:alert] = "Restricted/"
        redirect_to root_path
      end
    end

end

用户模型:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :shipments, dependent: :destroy
  has_many :friendships
  has_many :friends, through: :friendships
  has_many :inverse_friendships, :class_name => 'Friendship', 
                                 :foreign_key => 'friend_id'
  has_many :inverse_friends, :through => :inverse_friendships, :source => :user

end

Users 控制器(User 本身由 Devise 创建)

class UsersController < ApplicationController

  before_action :authenticate_user!

  def show
    @user = User.find(params[:id])
  end

  def my_friends
    @friendships = current_user.friends
  end

  def search
    @users = User.search(params[:search_param])
    if @users
      @users = current_user.except_current_user(@users)
      render partial: 'friends/lookup'
    else
      render status: :not_found, nothing: true
    end
  end

  private

    def require_same_user
      if current_user != set_user
        flash[:alert] = "Restricted."
        redirect_to root_path
      end
    end

    def set_user
      @user = User.find(params[:id])
    end

end

友谊模型:

class Friendship < ActiveRecord::Base

  belongs_to :user
  belongs_to :friend, class_name: 'User'
  has_many :shipments

end

友谊控制器:

class FriendshipsController < ApplicationController

  def index
    @friendships = Friendship.all
  end

  def create
    @friendship = current_user.friendships.build(:friend_id => params[:friend_id])
    if @friendship.save
      flash[:success] = "Added to friends."
      redirect_to my_friends_path
    else
      flash[:alert] = "Impossible to add as a friend."
      redirect_to my_friends_path
    end
  end

  def destroy
    @friendship = current_user.friendships.find_by(friend_id: params[:id])
    @friendship.destroy
    flash[:notice] = "Unfriended."
    redirect_to my_friends_path
  end

  private

    def name
      @name = friend_id.name
    end

end

架构:

create_table "friendships", force: :cascade do |t|
    t.integer  "user_id"
    t.integer  "friend_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "shipments", force: :cascade do |t|
    t.string   "name"
    t.integer  "length"
    t.integer  "width"
    t.text     "adress"
    t.integer  "user_id"
    t.datetime "created_at",         null: false
    t.datetime "updated_at",         null: false
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
    t.integer  "height"
    t.integer  "kg"
  end

  add_index "shipments", ["user_id"], name: "index_shipments_on_user_id"

  create_table "users", force: :cascade do |t|
    t.string   "email",                             default: "", null: false
    t.string   "encrypted_password",                default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",                     default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                                     null: false
    t.datetime "updated_at",                                     null: false
    t.string   "name"
    t.integer  "phone",                  limit: 30
    t.string   "username"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

发货表单视图(新):

<%= form_for(shipment, html: { multipart: true }) do |f| %>
<p>Choose a friend from your friendlist or fill the address field manually:</p>
<%= f.select :friend_id, user.friendships.map{ |friendship| 
                                    [friendship.friend.name, friendship.id] } %>
  <%= f.text_field :adress, placeholder: "Address and index" %>
  <%= f.submit "Submit", class: "button" %>
<% end %>

【问题讨论】:

  • 简而言之,是的,它会使用 ajax 来获取朋友的地址,但在这种情况下,您不需要在表单字段中执行任何操作 - 只需创建一个 javascript 可以绑定到的 div以文本格式显示地址。 -- 虽然我认为您可能缺少地址模型,因此您可以拥有地址的所有必要字段(街道名称/号码、额外信息/城市/地区/州/邮政编码)

标签: ruby-on-rails ajax devise associations


【解决方案1】:

使用 ActiveRecord::Base,您可以使用预先加载和嵌套表单来解决您的问题。

Eager 加载与主对象相关的对象,并使用嵌套形式显示相关对象。

【讨论】:

    猜你喜欢
    • 2021-10-05
    • 1970-01-01
    • 2021-11-19
    • 2020-04-09
    • 2013-01-04
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多