我在Rails应用程序中有一个表单,该表单正在发布但未保存输入数据。
服务提供商有能力定义不同的酒具,例如,他提供了1,3,6,12以及更多常规信息,这些信息显示在show.html.erb(wine_controller)中。
在show.html.erb中显示一个_form.html.erb,它使用Reservations_controller。
逻辑是,葡萄酒可以有很多保留。
当前,瓶子已保存到数据库,但总数未保存到数据库,因为由于瓶子是未定义的局部变量或方法,所以Reservations Controller给出了NoMethodError。
Wines Controller
class WinesController < ApplicationController
before_action :set_wine, except: [:index, :new, :create]
before_action :authenticate_user!, except: [:show]
before_action :is_authorised, only: [:details, :pricing, :description, :photo_upload, :more_details, :sets, :location, :update]
def index
@wines = current_user.wines
end
def new
@wine = current_user.wines.build
end
def create
@wine = current_user.wines.build(wine_params)
if @wine.save
redirect_to details_wine_path(@wine), notice: "Saved..."
else
flash[:alert] = "Something went wrong..."
render :new
end
end
def show
@photos = @wine.photos
@guest_reviews = @wine.guest_reviews
end
def details
end
def pricing
end
def description
end
def photo_upload
@photos = @wine.photos
end
def more_details
end
def sets
end
def location
end
def update
new_params = wine_params
new_params = wine_params.merge(active: true) if is_ready_wine
if @wine.update(wine_params)
flash[:notice] = "Saved..."
else
flash[:alert] = "Something went wrong..."
end
redirect_back(fallback_location: request.referer)
end
def preload
today = Date.today
# Reservations greater than today (upcoming reservations)
reservations = @wine.reservations.where("start_date >= ?", today)
render json: reservations
end
private
def set_wine
@wine = Wine.find(params[:id])
end
# Authorize user (current_user == ID 1)
def is_authorised
redirect_to root_path, alert: "You don't have permission" unless current_user.id == @wine.user_id
end
def is_ready_wine
!@wine.active && !@wine.price.blank? && !@wine.base_price.blank? && !@wine.wine_name.blank? && !@wine.summary.blank? && !@wine.photos.blank? && !@wine.alcohol.blank? && !@wine.filling.blank? && !@wine.in_stock.blank? && !@wine.address.blank?
end
def wine_params
params.require(:wine).permit(:wine_type, :wine_color, :wine_art, :alcohol, :wine_name, :summary, :address, :is_1, :is_3, :is_6, :is_12, :filling, :base_price, :price, :in_stock, :year, :active)
end
end
Reservation.rb
class Reservation < ApplicationRecord
before_save :update_financials
belongs_to :user
belongs_to :wine
def update_financials
total = wine.price * bottles if wine.present? && bottles.present?
price = wine.price if wine.present?
end
end
我的_form.html.erb助手功能
def wine_quantity(wine)
case
when wine.is_1 && wine.is_3 && wine.is_6 && wine.is_12 then [["1 Flasche", 1], ["3 Flaschen", 3], ["6 Flaschen", 6], ["12 Flaschen", 12]]
when wine.is_1 && wine.is_3 && wine.is_6 then [["1 Flasche", 1], ["3 Flaschen", 3], ["6 Flaschen", 6]]
when wine.is_1 && wine.is_3 && wine.is_12 then [["1 Flasche", 1], ["3 Flaschen", 3], ["12 Flaschen", 12]]
when wine.is_1 && wine.is_6 && wine.is_12 then [["1 Flasche", 1], ["6 Flaschen", 6], ["12 Flaschen", 12]]
when wine.is_1 && wine.is_12 then [["1 Flasche", 1], ["12 Flaschen", 12]]
when wine.is_1 && wine.is_6 then [["1 Flasche", 1], ["6 Flaschen", 6]]
when wine.is_1 && wine.is_3 then [["1 Flasche", 1], ["3 Flaschen", 3]]
else
end
end
如果提供商选择提供6瓶和12瓶,则form.html.erb中仅显示6瓶和12瓶
我的_form.html.erb:
<div class="panel-body">
<%= form_for([@wine, @wine.reservations.new]) do |f| %>
<div class="panel-body">
<div class="col-md-12">
<label>Lieferdatum</label>
<%= f.text_field :start_date, readonly: true, placeholder: "Lieferdatum", class: "form-control datepicker" %>
</div>
<!-- BUY SET? -->
<div class="col-md-12 select" style="margin-top:10px">
<div class="form-group">
<label>Anzahl an Flaschen</label>
<%= f.select :bottles, wine_quantity(@wine), {}, id: "bottles", prompt: "Auswählen...", class: "form-control" %>
</div>
</div>
</div>
<div id="preview" style="display:none">
<table class="reservation-table">
<tbody>
<tr>
<td>Preis pro Flasche</td>
<td class="text-right"><%= @wine.price %>€</td>
</tr>
<tr>
<td>Anzahl Flaschen</td>
<td class="text-right">x <span id="reservation_bottles"></span></td>
</tr>
<tr>
<td class="total">Gesamt</td>
<td class="text-right"><span id="reservation_total"></span>€</td>
</tr>
</tbody>
</table>
</div>
<br/>
<%= f.submit "Bestellen", id: "btn_book", class: "btn btn-normal btn-block", disabled: true %>
<% end %>
</div>
</div>
<script>
$(function() {
$.ajax({
url: '<%= preload_wine_path(wine_id: @wine.id) %>',
dataTyp: 'json',
success: function(data) {
var bottles = document.getElementById("bottles").value;
var total = bottles * <%= @wine.price %>
$('#reservation_bottles').text(bottles);
$('#reservation_total').text(total.toFixed(2));
$('#reservation_start_date').datepicker({
dateFormat: 'dd-mm-yy',
minDate: 2,
maxDate: '5d',
beforeShowDay: $.datepicker.noWeekends,
onSelect: function(selected) {
$('#preview').show();
$('#btn_book').attr('disabled', false);
$('#bottles').on('click', function() {
var bottles = $(this).val();
var total = bottles * <%= @wine.price %>
$('#reservation_bottles').text(bottles);
$('#reservation_total').text(total.toFixed(2));
});
}
});
}
});
});
</script>
我的预订控制器:
class ReservationsController < ApplicationController
before_action :authenticate_user!
def create
wine = Wine.find(params[:wine_id])
if current_user == wine.user
flash[:alert] = "Du kannst nicht deinen eigenen Wein kaufen!"
else
start_date = Date.parse(reservation_params[:start_date])
@reservation = current_user.reservations.build(reservation_params)
@reservation.wine = wine
@reservation.price = wine.price
@reservation.total = wine.price * bottles
@reservation.save
flash[:notice] = "Erfolgreich Bestellt!"
end
redirect_to wine
end
def your_orders
@orders = current_user.reservations.order(start_date: :asc)
@today = Date.today
end
def your_reservations
@wines = current_user.wines
end
# Each Order Details
def order_details
@orders = current_user.reservations.order(start_date: :asc)
end
private
def reservation_params
params.require(:reservation).permit(:start_date)
end
end
当我尝试将:bottles实现到Reservations_controller.rb中时,出现了NoMethodError ...我认为我正在将输入数据从form.html.erb解析到Reservations控制器中。
以下是请求:
{"utf8"=>"✓",
"authenticity_token"=>"3xgM8kSLwa+8JafBZYMoX+BA2XgelWY5bY7yENMrtqAxXCrBb6IabNFa72BG0H6jYnszkzZ/oilOLbka2mmVUA==",
"reservation"=>{"start_date"=>"26-10-2018", "bottles"=>"3"},
"commit"=>"Bestellen",
"wine_id"=>"3"}
答案 0 :(得分:0)
好像您的ajax正在将数据发送到另一个控制器。它不是将其发送到“葡萄酒”控制器的“预载”操作吗?
<script>
$(function() {
$.ajax({
// updated URL
url: '<%= reservation_path(wine_id: @wine.id) %>',
// updated datatype field name
dataType: 'json',
success: function(data) {
var bottles = document.getElementById("bottles").value;
var total = bottles * <%= @wine.price %>
$('#reservation_bottles').text(bottles);
$('#reservation_total').text(total);
$('#reservation_start_date').datepicker({
dateFormat: 'dd-mm-yy',
minDate: 2,
maxDate: '5d',
beforeShowDay: $.datepicker.noWeekends,
onSelect: function(selected) {
$('#preview').show();
$('#btn_book').attr('disabled', false);
$('#bottles').on('click', function() {
var bottles = $(this).val();
var total = bottles * <%= @wine.price %>
$('#reservation_bottles').text(bottles);
$('#reservation_total').text(total.toFixed(2));
});
}
});
}
});
});
</script>
还要在表单中为wine_id创建一个隐藏字段;注意:假设您使用的是form_for或form_with
<%= form.hidden_field :wine_id, @wine.id %>
看上去您的控制器还没有接受瓶子数据,因此您可能未正确引用它。我假设您的预订模型具有一个称为Bottles的字段,其中包含整数数据。因此,这是我建议的更改:
class ReservationsController < ApplicationController
def create
# you don't need to look up the wine to assign it the reservations; skip this
# wine = Wine.find(params[:wine_id])
# TBH, I would move this into a validation check
if current_user == wine.user
flash[:alert] = "Du kannst nicht deinen eigenen Wein kaufen!"
# don't you need to render the original page so the user can edit the choice? something like:
# render :new
else
# what are you using start_date for? seems like you should remove it
# start_date = Date.parse(reservation_params[:start_date])
@reservation = current_user.reservations.build(reservation_params)
# The math on reservation is more appropriate within the reservations model
if @reservations.save
flash[:notice] = "Erfolgreich Bestellt!"
else
# handle errors here
end
end
...
private
# you need to add bottles and wine_id to your permitted params
def reservation_params
params.require(:reservation).permit(:start_date, :bottles, :wine_id)
end
end
然后修改回调的预订模型
class Reservation < ActiveModel
# use a callback to update the model when fields are changed
before_save :update_financials
...
def update_financials
total = wine.price * bottles if wine.present? && bottles.present?
price = wine.price if wine.present?
end
end
最后一条评论,我可能会将current_user == wine.user
移至预订的有效性检查中。这稍微复杂一点,但是简化了控制器,并使您可以更轻松地在模型中对其进行测试。参见此处:https://guides.rubyonrails.org/active_record_validations.html#custom-methods