我正在做我的第一个项目,我需要你的帮助。 我正在使用act_as_shopping_cart gem和Rails Tutorial中的用户模型。 我如何绑定用户和购物车?我尝试绑定shopping_cart.id和user.id,但没有成功,仍然所有用户都有相同的购物车。 我的代码: 购物车控制器:
class ShoppingCartsController < ApplicationController
before_filter :extract_shopping_cart
def create
@product = Sketchbook.find(params[:product_id])
@shopping_cart.add(@product, @product.price)
redirect_to shop_path
end
def show
end
private
def extract_shopping_cart
shopping_cart_id = session[:shopping_cart_id]
@shopping_cart = session[:shopping_cart_id] ? ShoppingCart.find(shopping_cart_id) : ShoppingCart.create
session[:shopping_cart_id] = @shopping_cart.id
end
end
用户控制器:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:show, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to user_url(@user)
flash[:notice] = "Użytkownik stworzony"
else
render 'new'
end
end
def edit
end
def update
if @user.update_attributes(user_params)
redirect_to user_url(current_user)
flash[:notice] = "Dane zaktualizowane"
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Konto usunięte"
redirect_to root_url
end
private
def user_params
params.require(:user).permit(:username, :name, :surname, :email, :adress, :city, :zip_code, :country, :password, :password_confirmation)
end
#confirms a logged user
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Zaloguj się"
redirect_to login_url
end
end
#confirms the correct user
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
会话助手:
module SessionsHelper
#log in method
def log_in(user)
session[:user_id] = user.id
end
#remember a user in a presisnet session
def remember(user)
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
end
#returns true if the given user i current user
def current_user?(user)
user == current_user
end
#forgets a presistent session
def forget(user)
user.forget
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
# returns logged user
def current_user
if (user_id = session[:user_id]) #open broweser
@current_user ||= User.find_by(id: session[:user_id])
elsif (user_id = cookies.signed[:user_id]) #cookie is present
user= User.find_by(id: cookies.signed[:user_id])
if user && user.authenticated?(cookies[:remember_token])
log_in user
@current_user = user
end
end
end
# Returns true if the user is logged in
def logged_in?
!current_user.nil?
end
# logs out current user
def log_out
forget(current_user)
session.delete(:user_id)
@current_user = nil?
end
#stores the url trying to be accessed
def store_location
session[:forwarding_url] = request.url if request.get?
end
#redirect back to stored location (or to the default)
def redirect_back_or(default)
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
end
end
如果您能给我一些其他指导如何改进此代码,我也很高兴。
答案 0 :(得分:1)
Rails让你可以做很多“魔术”,其中一个地方的代码神奇地影响应用程序中其他地方的行为,两者之间没有明确的联系。这真的很强大,但我认为对于初学者来说,这也是一个巨大的问题;当你学习Rails时,很难跟踪一个东西是如何与另一个东西相关的,所以在继承链中隐藏这些连接几乎是残酷的。
所以,如果你在一个Rails魔术压倒性的地方(它当然对我而言),我的建议是编写愚蠢的代码,使连接成为本地和简单尽可能。有时甚至当它偏离“Rails方式”时也值得这样做;你宁愿拥有“正确的Rails”代码,还是易于理解和易于维护的代码?
无论如何,您的具体问题可能与会话有关。在ShoppingCartsController
中,您通过查找@shopping_cart
来定义session[:shopping_cart_id]
。如果多个用户(在注销并以其他人身份登录后)最终使用相同的@shopping_cart.id
,则必须表示其会话值相同。在相关控制器操作的开头,添加一个puts
语句,为您提供有关会话值的额外信息(它向控制台吐出):
puts session
如果多个用户具有相同的会话值,则可能意味着当您注销并以其他人身份登录时,会话未正确清除。您可以通过设置不同的会话变量来测试它,并查看是否也会从一个用户持续到另一个用户。
通常,在所有相关控制器操作的开头添加大量puts
语句是一种很好的(并且非常简单)方式,可以深入了解应用程序的思路。
希望有所帮助!