如何以多种形式访问多个模型
[英] How to access multiple models in multiple forms
本文介绍了如何以多种形式访问多个模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
首先,我要感谢 SO 的每一个人.在过去的几天里,我从你们那里得到了很多帮助,非常感谢!
我手上还有一个问题:
背景/目标:
我有一个游览、日间和预订模式.在我的游览控制器中,我可以创建游览并手动输入游览可用的天数.然后我想访问每个旅游预订页面 (tours/1/reservation/new) 并显示旅游信息以及旅游指定日期.
我的问题是:
1) 我需要在我的预订控制器和视图中输入什么才能访问选择标签中的每个旅行指定日期?
2) 是否有 Rails 方法可以将输入的一周中的天数转换为显示指定日期及其日期的动态形式?
例如:巡演 #1 每周一和周二可用(这些是在我创建巡演时手动输入的天数).我怎样才能把那些日子变成一个动态的形式,其中 Rails 显示每个月的每个星期一和星期二的日期?(我可能会为此发布另一个问题,只是想知道,因为它有点相关.)
深入的解释总是值得赞赏的,因为我有点无能为力.:(再次感谢您!
更新:
每次旅行的天数不会显示在预订页面上,如果它们在 form_helper 中,或者甚至是像我将引导程序下拉菜单类应用到周围元素这样简单的东西.
这有效:(显示天数)
<% @tour.days.all.each 做 |day|%><li><%= day.name %><%结束%>
这不会:
也不是这个:
<% @tour.days.each do |day|%><%= f.fields_for :day do |builder|%><%= builder.label :id, '可用天数:'%><br/><%= builder.select :id, options_from_collection_for_select(day, 'id', 'name') %><%结束%><%结束%>
我完全被难住了.
模型:
课程导览拉姆达 { |a|a[:name].空白?}, :allow_destroy =>真的结尾班级预订拉姆达 { |a|a[:name].空白?}, :allow_destroy =>真的结尾上课日ActiveRecord::Base归属地:游览has_many :reservations, 依赖: :destroyaccepts_nested_attributes_for :reservations, allow_destroy: true, :reject_if =>拉姆达 { |a|a[:name].空白?}, :allow_destroy =>真的结尾
迁移:
类 CreateTours <ActiveRecord::迁移定义改变create_table :tours do |t|t.string :namet.integer :amount
t.timestamps结尾结尾结尾类 CreateDays
观看次数:
游览
<div class="row"><div class="col-md-12"><h2>添加新游览</h2><%= bootstrap_form_for(@tour) 做 |f|%><%= f.text_field :name %><%= f.fields_for :days do |builder|%><%= builder.label :name, '游览天数:' %><%= builder.text_field :name, label: 'Days of Tour:' %><%= builder.check_box :_destroy %><%= builder.label :_destroy, '删除日期' %><%结束%><%= f.text_field :amount %><%= f.text_field :time %><%= f.submit '添加此游览' %><%结束%>
预订
<div class="容器"><div class="row"><div class="col-md-9"><h2><%=@tour.name %>
<div class="col-md-3"><p><%=@tour.amount %></p><%= bootstrap_form_for([:tour, @reservation], html: { class: 'form-horizontal', id: 'payment-form'}) do |f|%><%= f.alert_message '请修正以下错误:' %><%= f.select :passengers, options_for_select( (1..10).map { |n| n %1 == 0 ? n.to_i : n } ) %><%= f.fields_for :days do |builder|%><%= builder.label :name, '可用天数:'%><br/><%= builder.text_field :name %><%结束%><fieldset class="credit_card"><span class="payment-errors"></span></fieldset><div class="control-group"><%= label_tag :card_number, '信用卡号:', class: 'control-label' %><div class="控件"><%= text_field_tag :card_number, nil, name: nil, class: 'span3', data: {stripe: 'number'} %>
<div class="control-group"><%= label_tag :security_code, 'Security code:', class: 'control-label' %><div class="控件"><%= text_field_tag :security_code, nil, name: nil, class: 'span3', data: {stripe: 'cvc'} %>
<div class="control-group"><%= label_tag :exp_date, 'Expiration:', class: 'control-label' %><div class="控件"><%= select_month(Date.today, {add_month_numbers: true}, class: 'span2', data: {stripe: 'exp-month'}) %><%= select_year(Date.today.year, {start_year: Date.today.year, end_year: Date.today.year + 4}, class: 'span1', data: {stripe: 'exp-year'})%>
<fieldset class="actions control-group"><div class="控件"><%= f.submit '注册' %>
</fieldset><%结束%>
控制器:
class ReservationsController <应用控制器定义索引结尾定义新@reservation = Reservation.new@tour = Tour.find(params[:tour_id])结尾定义创建@tour = Tour.find(params[:tour_id])如果@reservation.update_attribute(:t_shirt, params[:t_shirt]) == true ||@reservation.update_attribute(:hat, params[:hat]) == true@tour.amount = @tour.amount + 15别的@tour.amount = @tour.amount结尾@reservation = Reservation.new(reservation_params)如果@reservation.saveStripe.api_key = ENV["STRIPE_SECRET_KEY"]Stripe::Charge.create(:金额=>@tour.amount, # 美分,再次:货币=>美元",:卡=>参数[:stripeToken])flash[:success] = "您的预订已为 #{@reservation.passengers} 人预订.请保存此信息."redirect_to new_tour_reservation_path(@tour)别的呈现新"结尾结尾私人的定义保留参数params.require(:reservation).permit(:date, :passengers, days_attributes: [:id, :name, :_destroy])
结束结束
class ToursController <应用控制器定义索引@tours = Tour.all结尾定义新@tour = Tour.new7.times { @tour.days.build }结尾定义创建@tour = Tour.new(tours_params)如果@tour.saveflash[:success] = "Tour #{@tour.name} 已成功添加."redirect_to new_tour_path别的flash[:error] = "巡演#{@tour.name} 没有成功保存.请重试"呈现新"结尾结尾高清秀@tour = Tour.find_by(id: params[:id])@reservation = Reservation.new结尾定义编辑@tour = Tour.find_by(id: params[:id])结尾定义更新@tour = Tour.find_by(id: params[:id])如果@tour.update_attributes(tours_params)flash[:success] = "#{@tour.name} 已成功更新."重定向到 tours_path别的flash[:error] = "#{@tour.name} 尚未更新.请重试."渲染编辑"结尾结尾定义删除@tour = Tour.find_by(id: params[:id])结尾销毁@tour = Tour.find_by(id: params[:id])如果@tour.destroyflash[:success] = "#{@tour.name} 已成功删除."重定向到 tours_path别的flash[:error] = "#{@tour.name} 尚未删除.请重试."渲染编辑"结尾结尾私人的def tours_paramsparams.require(:tour).permit(:name, :amount, days_attributes: [:id, :name, :_destroy])结尾结尾
路线:
Rails.application.routes.draw 做资源:旅游做资源:预订结尾结尾
解决方案
@tour.days
是一个数组,我相信.您需要的是单个实例.
看看这是否有效:
<% @tour.days.each do |day|%><%= f.fields_for :day do |builder|%><%= builder.label :id, '可用天数:'%><br/><%= builder.select :id, options_from_collection_for_select(day, 'id', 'name') %><%结束%><%结束%>
如果您在 API 中查找 options_from_collection_for_select
,您会注意到它们这个例子:
options_from_collection_for_select(@people, 'id', 'name')
@people
是单个对象.不是数组.其中 @tour.days
是一个数组
First, I want to thank everyone at SO. I've been getting a lot of help from you guys the last couple days and it's much appreciated!
I have another problem on my hands:
Background/Goal:
I have a Tour, Day, and Reservation model. In my Tour controller, I can create a tour and manually enter in days that the tour is available on. I then want to access each tours reservation page (tours/1/reservation/new) and display the tour information along with the tour designated days.
My question are:
1) What do I need to put in my reservations controller and view in order for me to access each tours designated days in a select tag?
2) Is there a Rails way to turn the inputted days of the week into a dynamic form where it displays the designated day and their dates?
For an example: Tour #1 is available on Mondays and Tuesdays (every week) (these are manually entered in days when I create the tour). How can I turn those days into a dynamic form where Rails displays the date of every Monday and Tuesday in each month? (I will probably post another question for this, just wondering since it's somewhat related.)
Deep explanations are always appreciated, as I'm a bit clueless. :( Thank you again!
UPDATE:
The days of each tour are NOT being displayed on the reservations page IF they're in a form_helper or even something as simple as me applying a bootstrap dropdown-menu class to the surrounding element.
This works: (shows days)
<ul>
<% @tour.days.all.each do |day| %>
<li>
<%= day.name %>
</li>
<% end %>
</ul>
This DOES NOT:
<ul class='dropdown-menu'>
<% @tour.days.all.each do |day| %>
<li>
<%= day.name %>
</li>
<% end %>
</ul>
NOR this:
<% @tour.days.each do |day| %>
<%= f.fields_for :day do |builder| %>
<%= builder.label :id, 'Days available:' %><br />
<%= builder.select :id, options_from_collection_for_select(day, 'id', 'name') %>
<% end %>
<% end %>
I'm completely stumped.
Models:
class Tour < ActiveRecord::Base
has_many :days, dependent: :destroy
has_many :reservations
accepts_nested_attributes_for :days, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Reservation < ActiveRecord::Base
belongs_to :tour
belongs_to :day
accepts_nested_attributes_for :days, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Day < ActiveRecord::Base
belongs_to :tour
has_many :reservations, dependent: :destroy
accepts_nested_attributes_for :reservations, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
Migrations:
class CreateTours < ActiveRecord::Migration
def change
create_table :tours do |t|
t.string :name
t.integer :amount
t.timestamps
end
end
end
class CreateDays < ActiveRecord::Migration
def change
create_table :days do |t|
t.string :name
t.integer :tour_id
t.timestamps
end
end
end
class CreateReservations < ActiveRecord::Migration
def change
create_table :reservations do |t|
t.integer :passengers
t.integer :tour_id
t.integer :day_id
t.timestamps
end
end
end
Views:
TOUR
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Add a new tour</h2>
<%= bootstrap_form_for(@tour) do |f| %>
<%= f.text_field :name %>
<%= f.fields_for :days do |builder| %>
<%= builder.label :name, 'Days of Tour:' %>
<%= builder.text_field :name, label: 'Days of Tour:' %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, 'Remove day' %>
<% end %>
<%= f.text_field :amount %>
<%= f.text_field :time %>
<%= f.submit 'Add this tour' %>
<% end %>
</div>
</div>
</div>
RESERVATION
</script>
<div class="container">
<div class="row">
<div class="col-md-9">
<h2>
<%= @tour.name %>
</h2>
</div>
<div class="col-md-3">
<p>
<%= @tour.amount %>
</p>
<%= bootstrap_form_for([:tour, @reservation], html: { class: 'form-horizontal', id: 'payment-form'}) do |f| %>
<%= f.alert_message 'Please fix the errors below:' %>
<%= f.select :passengers, options_for_select( (1..10).map { |n| n %1 == 0 ? n.to_i : n } ) %>
<%= f.fields_for :days do |builder| %>
<%= builder.label :name, 'Days available:' %><br />
<%= builder.text_field :name %>
<% end %>
<fieldset class="credit_card">
<span class="payment-errors"></span>
</fieldset>
<div class="control-group">
<%= label_tag :card_number, 'Credit card number:', class: 'control-label' %>
<div class="controls">
<%= text_field_tag :card_number, nil, name: nil, class: 'span3', data: {stripe: 'number'} %>
</div>
</div>
<div class="control-group">
<%= label_tag :security_code, 'Security code:', class: 'control-label' %>
<div class="controls">
<%= text_field_tag :security_code, nil, name: nil, class: 'span3', data: {stripe: 'cvc'} %>
</div>
</div>
<div class="control-group">
<%= label_tag :exp_date, 'Expiration:', class: 'control-label' %>
<div class="controls">
<%= select_month(Date.today, {add_month_numbers: true}, class: 'span2', data: {stripe: 'exp-month'}) %>
<%= select_year(Date.today.year, {start_year: Date.today.year, end_year: Date.today.year + 4}, class: 'span1', data: {stripe: 'exp-year'}) %>
</div>
</div>
<fieldset class="actions control-group">
<div class="controls">
<%= f.submit 'Sign up' %>
</div>
</fieldset>
<% end %>
</div>
</div>
</div>
Controllers:
class ReservationsController < ApplicationController
def index
end
def new
@reservation = Reservation.new
@tour = Tour.find(params[:tour_id])
end
def create
@tour = Tour.find(params[:tour_id])
if @reservation.update_attribute(:t_shirt, params[:t_shirt]) == true || @reservation.update_attribute(:hat, params[:hat]) == true
@tour.amount = @tour.amount + 15
else
@tour.amount = @tour.amount
end
@reservation = Reservation.new(reservation_params)
if @reservation.save
Stripe.api_key = ENV["STRIPE_SECRET_KEY"]
Stripe::Charge.create(
:amount => @tour.amount, # amount in cents, again
:currency => "usd",
:card => params[:stripeToken]
)
flash[:success] = "Your reservation has been booked for #{@reservation.passengers} person(s). Please save this info."
redirect_to new_tour_reservation_path(@tour)
else
render 'new'
end
end
private
def reservation_params
params.require(:reservation).permit(:date, :passengers, days_attributes: [:id, :name, :_destroy])
end
end
class ToursController < ApplicationController
def index
@tours = Tour.all
end
def new
@tour = Tour.new
7.times { @tour.days.build }
end
def create
@tour = Tour.new(tours_params)
if @tour.save
flash[:success] = "Tour #{@tour.name} has been successfully added."
redirect_to new_tour_path
else
flash[:error] = "The tour #{@tour.name} was not successfully saved. Please try again"
render 'new'
end
end
def show
@tour = Tour.find_by(id: params[:id])
@reservation = Reservation.new
end
def edit
@tour = Tour.find_by(id: params[:id])
end
def update
@tour = Tour.find_by(id: params[:id])
if @tour.update_attributes(tours_params)
flash[:success] = "#{@tour.name} has been successfully updated."
redirect_to tours_path
else
flash[:error] = "#{@tour.name} has not been updated. Please try again."
render 'edit'
end
end
def delete
@tour = Tour.find_by(id: params[:id])
end
def destroy
@tour = Tour.find_by(id: params[:id])
if @tour.destroy
flash[:success] = "The #{@tour.name} has been successfully deleted."
redirect_to tours_path
else
flash[:error] = "The #{@tour.name} has not been deleted. Please try again."
render 'edit'
end
end
private
def tours_params
params.require(:tour).permit(:name, :amount, days_attributes: [:id, :name, :_destroy])
end
end
Routes:
Rails.application.routes.draw do
resources :tours do
resources :reservations
end
end
解决方案
@tour.days
is an array, I believe. What you need is a single instance.
see if this works:
<% @tour.days.each do |day| %>
<%= f.fields_for :day do |builder| %>
<%= builder.label :id, 'Days available:' %><br />
<%= builder.select :id, options_from_collection_for_select(day, 'id', 'name') %>
<% end %>
<% end %>
if you look up options_from_collection_for_select
in the API, you'll notice they this example:
options_from_collection_for_select(@people, 'id', 'name')
@people
is a single object. not an array. where as @tour.days
is an array
这篇关于如何以多种形式访问多个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文