I have really been scratching my head on this and would greatly appreciate help. I have a store setup where people can take courses. I have a course model, order model, and coupon model. Here are the associations in the models
class Course < ActiveRecord::Base
belongs_to :category
has_many :orders
has_many :coupons
end
class Order < ActiveRecord::Base
belongs_to :course
belongs_to :user
belongs_to :coupon
end
class Coupon < ActiveRecord::Base
belongs_to :course
has_many :orders
end
I have a very simple coupon model setup that has code and newprice columns. I want the ability for someone to be able to fill out the coupon form on the new order page and it to update the price.
In my my view for new order I have two forms one for the new order and one for the coupon. How do check in my controller if a user has entered the correct coupon code? How do I update the coupon price to be shown instead of the course price?
here is my order controller
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
@orders = Order.all
end
def show
end
def new
course = Course.find(params[:course_id])
@course = Course.find(params[:course_id])
@order = course.orders.build
@coupon = Coupon.new
@user = current_user.id
@useremail = current_user.email
end
def discount
course = Course.find(params[:course_id])
@order = course.orders.build
@user = current_user.id
@useremail = current_user.email
end
def edit
end
def create
@order = current_user.orders.build(order_params)
if current_user.stripe_customer_id.present?
if @order.pay_with_current_card
redirect_to @order.course, notice: 'You have successfully purchased the course'
else
render action: 'new'
end
else
if @order.save_with_payment
redirect_to @order.course, notice: 'You have successfully purchased the course'
else
render action: 'new'
end
end
end
def update
if @order.update(order_params)
redirect_to @order, notice: 'Order was successfully updated.'
else
render action: 'edit'
end
end
def destroy
@order.destroy
redirect_to orders_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
@order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:course_id, :user_id, :stripe_card_token, :email)
end
end
You can accomplish this with an AJAX request using the form_for
helper with the :remote
option.
Summary
- Set
:remote
option totrue
for yourcoupons
form to submit the AJAX request. - Create controller action to handle the AJAX request from the form.
- Use JavaScript to respond to the controller action to update your
orders
form (the other form in your view) with the new price information, etc.
AJAX request using `:remote`
Here's some example code representing your coupon
form :
<%= form_for @coupon, method: :post, url: check_coupon_code_path, remote: true do |f| %>
<%= f.text_field :coupon_code, :placeholder => "Enter your coupon" %>
<%= f.submit "Submit Coupon Code" %>
<% end %>
Notice the following:
- The
:remote
option for theform_for
tag is set totrue
. - The
:url
option is the path to your controller action in yourCouponsController
. Because the:remote
option is set totrue
, the request will be posted to this:url
option as an AJAX request. - In this code example, it's assuming it has a route defined like this in the
routes.rb
file to handle the AJAX request for checking the coupon code:post 'check_coupon_code' => 'coupons#check_coupon_code'
- Note: In the
forms_for
helper, the:url
option appends_path
to the prefix defined in theroutes.rb
file. - Bonus note: Use the command
rake routes
to see the available routes and their respective controller action targets.
Handle AJAX request in the Controller
In your CouponsController
, define the action check_coupon_code
to handle your AJAX request from the above form_for
:
def check_coupon_code
# logic to check for coupon code here
respond_to do |format|
if # coupon code is valid
format.js {}
else
# some error here
end
end
end
Notice the format.js
in the respond_to
block of the action. This allows the controller to respond to the AJAX request with JavaScript to update your orders
form in your view. You'll have to define a corresponding app/views/coupons/check_coupon_code.js.erb
view file that generates the actual JavaScript code that will be sent and executed on the client side (or name the JavaScript file check_coupon_code.js.coffee
if you're using CoffeeScript).
Updating with JavaScript
The JavaScript in your check_coupon_code.js.erb
file will then update the price in your order
form.
WARNING: Even if you use JavaScript to change the order price on the client-side (i.e. the browser), it is critical to validate the actual price again in the back-end (i.e. in your controller) in case some malicious user tries to manipulate the browser's request, etc.
You can see the official RailsGuide for another example.
来源:https://stackoverflow.com/questions/23277917/ruby-on-rails-and-coupon-model