Ruby 于 Rails 'has_many :through',正在存储数据
Ruby on Rails 'has_many :through', storing data
在我的应用程序中,我有一个 "bookings" table 和一个 "extras" table。
这是一个多对多的关系。因此我创建了一个名为 "additions"
的中间 table
我已经使用 "has_many :through" 建立了 table 之间的关系:
class Booking < ActiveRecord::Base
has_many :additions
has_many :extras, :through => :additions
class Extra < ActiveRecord::Base
has_many :additions
has_many :extras, :through => :additions
class Addition < ActiveRecord::Base
belongs_to :booking
belongs_to :extra
这似乎有效。我手动向一些现有预订添加了一些额外服务(通过添加数字 table),并编写了代码,以便当您单击以显示预订时,它会列出所有相关的额外服务。
现在我需要做到这一点,以便在您进行预订时 - "extras" 保存到中间(添加项)table。
我的预订表单页面上有复选框:
<%= f.label 'Extras:' %>
<%= f.collection_check_boxes :extra_ids, Extra.all, :id, :extra_info %>
但很明显,当用户点击保存时,选择就会被丢弃。
我需要一些代码(在控制器中?)将这些 "extras" 保存到 "additions table" ?
任何想法,因为我不知道该怎么做?!
谢谢!
class BookingsController < ApplicationController
respond_to :html, :xml, :json
before_action :find_room
# before_action :find_extra
def index
@bookings = Booking.where("room_id = ? AND end_time >= ?", @room.id, Time.now).order(:start_time)
respond_with @bookings
end
def new
@booking = Booking.new(room_id: @room.id)
end
def create
@booking = Booking.new(params[:booking].permit(:room_id, :start_time, :length, :user_id))
@booking.room = @room
if @booking.save
redirect_to room_bookings_path(@room, method: :get)
else
render 'new'
end
end
def show
@booking = Booking.find(params[:id])
end
def destroy
@booking = Booking.find(params[:id]).destroy
if @booking.destroy
flash[:notice] = "Booking: #{@booking.start_time.strftime('%e %b %Y %H:%M%p')} to #{@booking.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
redirect_to room_bookings_path(@room)
else
render 'index'
end
end
def edit
@booking = Booking.find(params[:id])
end
def update
@booking = Booking.find(params[:id])
# @booking.room = @room
if @booking.update(params[:booking].permit(:room_id, :start_time, :length, :user_id))
flash[:notice] = 'Your booking was updated succesfully'
if request.xhr?
render json: {status: :success}.to_json
else
redirect_to resource_bookings_path(@room)
end
else
render 'edit'
end
end
private
def save booking
if @booking.save
flash[:notice] = 'booking added'
redirect_to room_booking_path(@room, @booking)
else
render 'new'
end
end
def find_room
if params[:room_id]
@room = Room.find_by_id(params[:room_id])
end
end
# def find_extra
# if params[:extra_id]
# @extra = Extra.find_by_id(params[:extra_id])
# end
# end
# If resource not found redirect to root and flash error.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Booking not found."
end
def booking_params
params.require(:booking).permit(:user_id, :extra_id)
end
end
------------------------
class AdditionsController < ApplicationController
before_action :set_addition, only: [:show, :edit, :update, :destroy]
# GET /additions
def index
@additions = Addition.all
end
# GET /additions/1
def show
end
# GET /additions/new
def new
@addition = Addition.new
end
# GET /additions/1/edit
def edit
end
# POST /additions
def create
@addition = Addition.new(addition_params)
if @addition.save
redirect_to @addition, notice: 'Addition was successfully created.'
else
render :new
end
end
# PATCH/PUT /additions/1
def update
if @addition.update(addition_params)
redirect_to @addition, notice: 'Addition was successfully updated.'
else
render :edit
end
end
# DELETE /additions/1
def destroy
@addition.destroy
redirect_to additions_url, notice: 'Addition was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_addition
@addition = Addition.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def addition_params
params.require(:addition).permit(:booking_id, :extra_id, :extra_name)
end
end
--------------------------------------
# @author Stacey Rees <https://github.com/staceysmells>
class ExtrasController < ApplicationController
# @see def resource_not_found
around_filter :resource_not_found
before_action :set_extra, only: [:show, :edit, :update, :destroy]
def index
@extras = Extra.all
end
def show
end
def new
@extra = Extra.new
end
def edit
end
def create
@extra = Extra.new(extra_params)
if @extra.save
redirect_to @extra, notice: 'Extra was successfully created.'
else
render :new
end
end
def update
if @extra.update(extra_params)
redirect_to @extra, notice: 'Extra was successfully updated.'
else
render :edit
end
end
def destroy
@extra.destroy
redirect_to extras_url, notice: 'Extra was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_extra
@extra = Extra.find(params[:id])
end
# If resource not found redirect to root and flash error.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Room Category not found."
end
# Only allow a trusted parameter "white list" through.
def extra_params
params.require(:extra).permit(:extraimg, :name, :description, :quantity, :price, :extracat_id)
end
end
您在这里所做的是使用嵌套表单属性。它有点复杂,但也是人们经常做的事情,所以有一些很好的资源可用。
我建议你看看这个post:http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/
特别是,名为“More Complicated Relationships”的部分有一个使用嵌套属性设置多对多关联的示例,使用 has_many :through
。
关键部分(评论者已经指出)将是您的预订模型中的 accepts_nested_attributes_for :extras
,以及视图中的 f.fields_for :extras
块。您还需要修改 booking_params
方法以允许嵌套值。您可能会 运行 遇到一些严重的参数陷阱,因此您可能需要查看 the documentation.
事实证明,一旦 accepts_nested_attributes_for
被写入,我的代码就快完成了。
我的主要问题是在控制器中设置 booking_params 方法。我通过在 params.permit.
中声明 :extra_ids => []
使其工作
在我的应用程序中,我有一个 "bookings" table 和一个 "extras" table。
这是一个多对多的关系。因此我创建了一个名为 "additions"
的中间 table我已经使用 "has_many :through" 建立了 table 之间的关系:
class Booking < ActiveRecord::Base
has_many :additions
has_many :extras, :through => :additions
class Extra < ActiveRecord::Base
has_many :additions
has_many :extras, :through => :additions
class Addition < ActiveRecord::Base
belongs_to :booking
belongs_to :extra
这似乎有效。我手动向一些现有预订添加了一些额外服务(通过添加数字 table),并编写了代码,以便当您单击以显示预订时,它会列出所有相关的额外服务。
现在我需要做到这一点,以便在您进行预订时 - "extras" 保存到中间(添加项)table。
我的预订表单页面上有复选框:
<%= f.label 'Extras:' %>
<%= f.collection_check_boxes :extra_ids, Extra.all, :id, :extra_info %>
但很明显,当用户点击保存时,选择就会被丢弃。
我需要一些代码(在控制器中?)将这些 "extras" 保存到 "additions table" ?
任何想法,因为我不知道该怎么做?!
谢谢!
class BookingsController < ApplicationController
respond_to :html, :xml, :json
before_action :find_room
# before_action :find_extra
def index
@bookings = Booking.where("room_id = ? AND end_time >= ?", @room.id, Time.now).order(:start_time)
respond_with @bookings
end
def new
@booking = Booking.new(room_id: @room.id)
end
def create
@booking = Booking.new(params[:booking].permit(:room_id, :start_time, :length, :user_id))
@booking.room = @room
if @booking.save
redirect_to room_bookings_path(@room, method: :get)
else
render 'new'
end
end
def show
@booking = Booking.find(params[:id])
end
def destroy
@booking = Booking.find(params[:id]).destroy
if @booking.destroy
flash[:notice] = "Booking: #{@booking.start_time.strftime('%e %b %Y %H:%M%p')} to #{@booking.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
redirect_to room_bookings_path(@room)
else
render 'index'
end
end
def edit
@booking = Booking.find(params[:id])
end
def update
@booking = Booking.find(params[:id])
# @booking.room = @room
if @booking.update(params[:booking].permit(:room_id, :start_time, :length, :user_id))
flash[:notice] = 'Your booking was updated succesfully'
if request.xhr?
render json: {status: :success}.to_json
else
redirect_to resource_bookings_path(@room)
end
else
render 'edit'
end
end
private
def save booking
if @booking.save
flash[:notice] = 'booking added'
redirect_to room_booking_path(@room, @booking)
else
render 'new'
end
end
def find_room
if params[:room_id]
@room = Room.find_by_id(params[:room_id])
end
end
# def find_extra
# if params[:extra_id]
# @extra = Extra.find_by_id(params[:extra_id])
# end
# end
# If resource not found redirect to root and flash error.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Booking not found."
end
def booking_params
params.require(:booking).permit(:user_id, :extra_id)
end
end
------------------------
class AdditionsController < ApplicationController
before_action :set_addition, only: [:show, :edit, :update, :destroy]
# GET /additions
def index
@additions = Addition.all
end
# GET /additions/1
def show
end
# GET /additions/new
def new
@addition = Addition.new
end
# GET /additions/1/edit
def edit
end
# POST /additions
def create
@addition = Addition.new(addition_params)
if @addition.save
redirect_to @addition, notice: 'Addition was successfully created.'
else
render :new
end
end
# PATCH/PUT /additions/1
def update
if @addition.update(addition_params)
redirect_to @addition, notice: 'Addition was successfully updated.'
else
render :edit
end
end
# DELETE /additions/1
def destroy
@addition.destroy
redirect_to additions_url, notice: 'Addition was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_addition
@addition = Addition.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def addition_params
params.require(:addition).permit(:booking_id, :extra_id, :extra_name)
end
end
--------------------------------------
# @author Stacey Rees <https://github.com/staceysmells>
class ExtrasController < ApplicationController
# @see def resource_not_found
around_filter :resource_not_found
before_action :set_extra, only: [:show, :edit, :update, :destroy]
def index
@extras = Extra.all
end
def show
end
def new
@extra = Extra.new
end
def edit
end
def create
@extra = Extra.new(extra_params)
if @extra.save
redirect_to @extra, notice: 'Extra was successfully created.'
else
render :new
end
end
def update
if @extra.update(extra_params)
redirect_to @extra, notice: 'Extra was successfully updated.'
else
render :edit
end
end
def destroy
@extra.destroy
redirect_to extras_url, notice: 'Extra was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_extra
@extra = Extra.find(params[:id])
end
# If resource not found redirect to root and flash error.
def resource_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to root_url, :notice => "Room Category not found."
end
# Only allow a trusted parameter "white list" through.
def extra_params
params.require(:extra).permit(:extraimg, :name, :description, :quantity, :price, :extracat_id)
end
end
您在这里所做的是使用嵌套表单属性。它有点复杂,但也是人们经常做的事情,所以有一些很好的资源可用。
我建议你看看这个post:http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/
特别是,名为“More Complicated Relationships”的部分有一个使用嵌套属性设置多对多关联的示例,使用 has_many :through
。
关键部分(评论者已经指出)将是您的预订模型中的 accepts_nested_attributes_for :extras
,以及视图中的 f.fields_for :extras
块。您还需要修改 booking_params
方法以允许嵌套值。您可能会 运行 遇到一些严重的参数陷阱,因此您可能需要查看 the documentation.
事实证明,一旦 accepts_nested_attributes_for
被写入,我的代码就快完成了。
我的主要问题是在控制器中设置 booking_params 方法。我通过在 params.permit.
中声明:extra_ids => []
使其工作