Ich habe 3 Modelle - Benutzer, Versand und Freundschaft. Benutzer kann mit einem anderen Benutzer über Friendship-Modell befreundet sein. Der Benutzer kann auch Sendungen erstellen und ihm einen Freund-Benutzer hinzufügen. Es gibt ein Adressattribut in den Benutzer- und Versandmodellen. Ich muss dem Benutzer eine Möglichkeit geben, dieses Adressfeld auf zwei Arten auf dem gleichen Formular zu füllen:Wie füllt man mehrere Formularfelder mit einem Attribut aus einem anderen Modell?
Ich kann schätzen, dass AJAX benötigt wird, um den Inhalt zu aktualisieren, ohne die Seite zu aktualisieren.
Versand Modell:
class Shipment < ActiveRecord::Base
belongs_to :user
belongs_to :friendship
validates :image, presence: true
validates :user_id, presence: true
end
Sendungen Controller:
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
User-Modell:
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
Benutzer-Controller (der Benutzer selbst durch Devise erstellt wird)
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
Friendship Modell:
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: 'User'
has_many :shipments
end
Friendships Controller:
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
Schema:
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
Sendungsformularansicht (neu):
<%= 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 %>
Kurz gesagt, ja, es würde Ajax verwenden, um die Adresse des Freundes zu packen, aber Sie müssten in den Formularfeldern in diesem Fall nichts tun - erstellen Sie einfach ein div, an das JavaScript binden könnte, um die Adresse im Text anzuzeigen Format. - Obwohl ich denke, dass Sie ein Adressmodell vermissen, können Sie alle notwendigen Felder einer Adresse (Straßenname/Nummer, zusätzliche Informationen/Stadt/Region/Bundesland/Postleitzahl) haben – trh