This is the first time I''m developing a site with rails (online shop) and I really would like to ask for help with authetication. I''ve installed acts_as_autheticated and I set up that certain pages can only be viewed if the user logs in (for example editing or adding new products). I am just trying to get my head around certain roles for certain users. How should I go around creating different roles for different users? what if I want to make it mandatory for customers to log in in order to complete a transaction? I also discovered RoleRequirement yesterday on Google code. Should I use this plugin? Would anyone know any good tutorail to teach me how to accomplish this? Please help. Elle --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
The trick I did was to add flags to the user table, which is what
acts_as_authenticated is pointed at in my case.
These flags:
superadmin, a boolean, defaults to false
forumadmin, a boolean, defaults to false
banned, a boolean, defaults to false
I modified lib/authenticated_system.rb to teach it that I ALWAYS want
a current_user, and that it can never be nil. I can send you some
diffs if you want. The purpose in this is so I can write code that
reads like:
current_user.superadmin?
without having to write:
if !current_user.nil? && current_user.superadmin?
--Michael
On 10/11/07, elle <waznelle-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:>
> This is the first time I''m developing a site with rails (online
shop)
> and I really would like to ask for help with authetication.
>
> I''ve installed acts_as_autheticated and I set up that certain
pages
> can only be viewed if the user logs in (for example editing or adding
> new products). I am just trying to get my head around certain roles
> for certain users.
> How should I go around creating different roles for different users?
> what if I want to make it mandatory for customers to log in in order
> to complete a transaction?
>
> I also discovered RoleRequirement yesterday on Google code. Should I
> use this plugin?
> Would anyone know any good tutorail to teach me how to accomplish
> this?
>
> Please help.
>
> Elle
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Thanks Michael. Would appreciate anything you can send me about this. This might seem like a really silly question: Do I use the same users model for both admins and cutomers? Because the way, my logic works is to create another table of customers and have it under admin control. My logic also says that I will have the following relationships: Customer has many orders Order belongs to one customer But then, can I use the same acts_as_authenticated to get the cutomers to login? And how do I do this? And am I missing something with my relationships? Many questions, I know :-/ Thanks, Elle On Oct 12, 4:07 pm, "Michael Graff" <skan.gryp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> The trick I did was to add flags to the user table, which is what > acts_as_authenticated is pointed at in my case. > > These flags: > > superadmin, a boolean, defaults to false > forumadmin, a boolean, defaults to false > banned, a boolean, defaults to false > > I modified lib/authenticated_system.rb to teach it that I ALWAYS want > a current_user, and that it can never be nil. I can send you some > diffs if you want. The purpose in this is so I can write code that > reads like: > > current_user.superadmin? > > without having to write: > > if !current_user.nil? && current_user.superadmin? > > --Michael > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
randomutterings-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2007-Oct-12 14:47 UTC
Re: Authentication Help
I took the approach of using roles and rights. A user has and belongs
to many roles and a role has many rights. A right would be to a
specific action on a specific controller. Then just use a before
filter in your application.rb to check if the user has a role that has
the right to access the action in the controller he is trying to
access. It sounds more complicated than it is but it works great and
its very flexible. Here is some code to get you started if you''re
interested in doing it this way.
role.rb
----------------------------
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
has_and_belongs_to_many :rights
validates_uniqueness_of :name
def has_right_for?(action_name, controller_name)
rights.detect{ |right| right.has_right_for?(action_name,
controller_name) }
end
end
-----------------------------
right.rb
-----------------------------
class Right < ActiveRecord::Base
has_and_belongs_to_many :roles
def has_right_for?(action_name, controller_name)
action == action_name && controller == controller_name
end
end
_________________
user.rb
------------------------------
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
def has_right_for?(action_name, controller_name)
roles.detect{ |role| role.has_right_for?(action_name,
controller_name) }
end
end
-------------------------------
application.rb
-------------------------------
class ApplicationController < ActionController::Base
before_filter :check_authorization
def check_authorization
if session[:user].blank?
flash[:error] = "You must login to view the page you requested"
redirect_to :action => "login",
:controller => "user"
return false
end
# logged in users can view the following pages with out an
explicit right
unless action_name == "logout" || action_name =~ %r{my_}
unless has_right?(action_name, self.class.controller_path)
flash[:error] = "You are not authorized to view the page you
requested"
redirect_to :action => "index", :controller =>
"home"
return false
end
end
end
def has_right?(action_name, controller_name)
unless session[:user].blank?
user = User.find(session[:user])
user.has_right_for?(action_name, controller_name)
end
end
end
----------------------------------
Just use skip_before_filter on any actions you want open to users who
are not logged in (don''t forget to do this on the login page!)
On Oct 12, 1:52 am, elle
<wazne...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:> Thanks Michael. Would appreciate anything you can send me about this.
>
> This might seem like a really silly question:
> Do I use the same users model for both admins and cutomers?
> Because the way, my logic works is to create another table of
> customers and have it under admin control.
> My logic also says that I will have the following relationships:
> Customer has many orders
> Order belongs to one customer
>
> But then, can I use the same acts_as_authenticated to get the cutomers
> to login?
> And how do I do this?
> And am I missing something with my relationships?
>
> Many questions, I know :-/
>
> Thanks,
> Elle
>
> On Oct 12, 4:07 pm, "Michael Graff"
<skan.gryp...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> > The trick I did was to add flags to the user table, which is what
> > acts_as_authenticated is pointed at in my case.
>
> > These flags:
>
> > superadmin, a boolean, defaults to false
> > forumadmin, a boolean, defaults to false
> > banned, a boolean, defaults to false
>
> > I modified lib/authenticated_system.rb to teach it that I ALWAYS want
> > a current_user, and that it can never be nil. I can send you some
> > diffs if you want. The purpose in this is so I can write code that
> > reads like:
>
> > current_user.superadmin?
>
> > without having to write:
>
> > if !current_user.nil? && current_user.superadmin?
>
> > --Michael
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
On Oct 13, 1:47 am, "randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org" <randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I took the approach of using roles and rights. A user has and belongs > to many roles and a role has many rights. A right would be to a > specific action on a specific controller. Then just use a before > filter in your application.rb to check if the user has a role that has > the right to access the action in the controller he is trying to > access. It sounds more complicated than it is but it works great and > its very flexible. Here is some code to get you started if you''re > interested in doing it this way.Thanks Michael. I really wanted to have a separate model for Customer (bacause I have about 3 admins, 4 staff and 150 customers). I also wanted to have a relationship between customers and orders (to show orders per customer). But i''ve spend all yesterday and today on it and I just don''t know how to implement it. Any advice, before I give in and just use one User model for everyone? Elle --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
In nearly all my applications, I do something far more complicated. But to answer your question, I use one table for "things that can log in" and have a default-false "is admin" flag. I want to write the roles/permissions model thing, and intend to do it eventually, so if you can that''s the most flexible but most complicated to get started on method. No matter what you choose, I would suggest having an is_admin? method that you can use in your checks. Then should you change your method from a simple flag to a full-blown roles/rights system, you don''t have to change as much code. The more complicated thing I do is this: Since most users eventually report a problem, I have a way for an admin to set themselves up as an "effective user" -- that is, they can become that user for all purposes, and see exactly what the user would see. The only difference is they cannot complete certain operations without a small dialog box saying something like: "You are in administrative mode, and are making this change as user <username>. Do you really want to do this?" --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Oct 14, 2007, at 12:45 , Michael Graff wrote:> The more complicated thing I do is this: Since most users eventually > report a problem, I have a way for an admin to set themselves up as an > "effective user" -- that is, they can become that user for all > purposes, and see exactly what the user would see.This is on my list of features to implement on a current project. I haven''t yet done any research for how others have done this (which I intend to do when I get to that feature), but since you brought it up I was wondering if you''d care to share how you did this. Michael Glaesemann grzm seespotcode net --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I ended up with the following:
1) For admin pages: I used acts_as_authenticated plugin for users (and
by users I mean admins).
My aaplication.rb controller has:
class ApplicationController < ActionController::Base
include AuthenticatedSystem
...
My base_controller.rb for the admin area inherits from the
ApplicationController and also has a before_filter:
class Admin::BaseController < ApplicationController
before_filter :login_required
end
And all my admin pages inherit from the base controller by using:
class Admin::UserController < Admin::BaseController
...
Which means, they all require login to be viewed.
In my views/layout/application.rhtml I have:
<p id="adminlogin">
<% if logged_in? %>
Logged in as <%= current_user.login %>
(<%= link_to "Logout", :controller => "/admin",
:action =>
"logout" %>)
<% else %>
<%= link_to "Admin Login", :controller =>
"/admin", :action =>
"login" %>
<% end %>
</p>
2) Next, I added another column in my users table called
''role'' (:integer, :limit => 1) to identify 1 for manager
and 0 for
staff.
Only managers can add admins. Staff can do everything else in the
admin area besides administering admins.
So, in my user_controller.rb I added another before_filter:
before_filter :check_authorization
def check_authorization
user = User.find(session[:user])
unless user.role?
flash[:notice] = "You are not authorized to view the page
requested"
redirect_to :controller => ''product'', :action =>
''index''
return false
end
end
3) Lastly, I created a customer model which admins can create,
edit....
Now, only logged customers can checkout. So, in my checkout controller
I added all my customer''s login methods, like so:
class CheckoutController < ApplicationController
before_filter :initialize_cart
before_filter :authorize, :except => ["login"]
def authorize
return true if @c
flash[:notice] = "To place your order please login"
redirect_to :controller => "catalog"
end
def login
# examine the form data for "name" and "password"
pw,name = params[:customer].values_at(*%w{password name})
# Retrieve the customer record for the name and store it in a
variable ''c''
c = Customer.find_by_name(name)
# if such record exists, and it''s password matches the password
from the form
if c && Digest::SHA1.hexdigest(pw) == c.password
# start a session with the customer id
@session[''customer''] = c.id
if @cart.products.empty?
redirect_to :controller => "catalog"
else
redirect_to :controller => "checkout", :action =>
"index"
end
else
# otherwise report an error
flash[:notice] = "Invalid Login"
end
end
def logout
@session[''customer''] = nil
redirect_to :controller => "catalog"
end
And in my application.rb controller:
# register the method get_customer as a filter
before_filter :get_customer
def get_customer
# sets an instance variable @c to the customer object
# drawn from the db record of the customer who''s logged in
# else the method is not assigned to @c and @c defaults to nil
if @session[''customer'']
@c = Customer.find(@session[''customer''])
end
end
This login method is taken from "Ruby from Rails" book, Part 4, which
I am going to use next to change my current cart.
I am going to change it that both cart and checkout are in the same
controller because I need the cart to belongs_to :customer.
The reason is that I need to apply the customer''s discount level and I
also want to record the customer''s id in the orders table.
(optional later, I will add the option to remember customer''s shipping
address.)
This has been a huge learning curve for me. I''m happy (and tired) that
it finally works. I''m off to re-do my cart.
If you have any suggestions/improvements to my code or way of
thinking, please share your thoughts.
Just one last question, when I create a session, does the information
for session[''customer''] and session[:cart_id] get stored in
the same
file?
and How do I call on the customer_id from the session? Have run into
trouble with this, where the order recorded the order_id in the
customer_id column. Not sure where is my mistake yet.
Cheers,
Elle
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
Each session is stored in a single file in binary format. It looks like you are storing the customer id as session["customer"] so you can just reference it like that. Can you post your code with the order_id problem? On Oct 14, 10:10 pm, elle <wazne...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I ended up with the following: > 1) For admin pages: I used acts_as_authenticated plugin for users (and > by users I mean admins). > > My aaplication.rb controller has: > class ApplicationController < ActionController::Base > include AuthenticatedSystem > ... > > My base_controller.rb for the admin area inherits from the > ApplicationController and also has a before_filter: > class Admin::BaseController < ApplicationController > before_filter :login_required > end > > And all my admin pages inherit from the base controller by using: > class Admin::UserController < Admin::BaseController > ... > Which means, they all require login to be viewed. > > In my views/layout/application.rhtml I have: > <p id="adminlogin"> > <% if logged_in? %> > Logged in as <%= current_user.login %> > (<%= link_to "Logout", :controller => "/admin", :action => > "logout" %>) > <% else %> > <%= link_to "Admin Login", :controller => "/admin", :action => > "login" %> > <% end %> > </p> > > 2) Next, I added another column in my users table called > ''role'' (:integer, :limit => 1) to identify 1 for manager and 0 for > staff. > Only managers can add admins. Staff can do everything else in the > admin area besides administering admins. > So, in my user_controller.rb I added another before_filter: > > before_filter :check_authorization > > def check_authorization > user = User.find(session[:user]) > unless user.role? > flash[:notice] = "You are not authorized to view the page > requested" > redirect_to :controller => ''product'', :action => ''index'' > return false > end > end > > 3) Lastly, I created a customer model which admins can create, > edit.... > Now, only logged customers can checkout. So, in my checkout controller > I added all my customer''s login methods, like so: > > class CheckoutController < ApplicationController > before_filter :initialize_cart > before_filter :authorize, :except => ["login"] > > def authorize > return true if @c > flash[:notice] = "To place your order please login" > redirect_to :controller => "catalog" > end > > def login > # examine the form data for "name" and "password" > pw,name = params[:customer].values_at(*%w{password name}) > # Retrieve the customer record for the name and store it in a > variable ''c'' > c = Customer.find_by_name(name) > # if such record exists, and it''s password matches the password > from the form > if c && Digest::SHA1.hexdigest(pw) == c.password > # start a session with the customer id > @session[''customer''] = c.id > if @cart.products.empty? > redirect_to :controller => "catalog" > else > redirect_to :controller => "checkout", :action => "index" > end > else > # otherwise report an error > flash[:notice] = "Invalid Login" > end > end > > def logout > @session[''customer''] = nil > redirect_to :controller => "catalog" > end > > And in my application.rb controller: > # register the method get_customer as a filter > before_filter :get_customer > > def get_customer > # sets an instance variable @c to the customer object > # drawn from the db record of the customer who''s logged in > # else the method is not assigned to @c and @c defaults to nil > if @session[''customer''] > @c = Customer.find(@session[''customer'']) > end > end > > This login method is taken from "Ruby from Rails" book, Part 4, which > I am going to use next to change my current cart. > I am going to change it that both cart and checkout are in the same > controller because I need the cart to belongs_to :customer. > The reason is that I need to apply the customer''s discount level and I > also want to record the customer''s id in the orders table. > (optional later, I will add the option to remember customer''s shipping > address.) > > This has been a huge learning curve for me. I''m happy (and tired) that > it finally works. I''m off to re-do my cart. > If you have any suggestions/improvements to my code or way of > thinking, please share your thoughts. > > Just one last question, when I create a session, does the information > for session[''customer''] and session[:cart_id] get stored in the same > file? > and How do I call on the customer_id from the session? Have run into > trouble with this, where the order recorded the order_id in the > customer_id column. Not sure where is my mistake yet. > > Cheers, > Elle--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
The basics are:
(1) When an admin requests to become another user, I set a session
variable called:
session[:effective_user] = User.find_by_login("whatever")
(2) When they stop being that user, I delete that entry from the session hash.
(3) When I set up my current_user pseudo-global, I set it to the
effective user if it is set, or to the real user (in session[:user])
if it is not set.
(4) I set real_user to session[:user]
(5) Once those are set up, I verify that this is true:
current_user == real_user || real_user.is_site_admin?
This prevents a mistake from letting someone become another user where
they should not.
(6) In most places, I use current_user for all access checking,
display, and database updates.
(7) In specific places where I want the admin to be warned (deleting
data, changing data in some cases, and also on a "WARNING: you are
logged in as ..." on the sidebar menu) I check to see if real_user
!current_user && current_user.is_site_admin?
Since I use current_user nearly everywhere, this was the path of least
rototill for me :)
--Michael
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
This is slightly different but still on the same subject.
So, I got the customer to log in, but.... he doesn''t have a cart that
belongs to him. Which means if another customer logs in, they see the
other''s cart. I want to associate the cart with a customer to also be
able to record the customer''s id in the orders table. but.... I
don''t
know how to do that.
Other problems that I have with my cart are:
1) Update doesn''t happen
2) checkout page suddenly doesn''t appear
Will you have a look at how I can associate the cart with the logged
in customer? (And if you can at the other questions/problems)
My cart.rb:
--------------------
class Cart < ActiveRecord::Base
has_many :cart_items
has_many :products, :through => :cart_items
belongs_to :customer
def total
cart_items.inject(0) {|sum, n| n.price * n.amount + sum}
end
def add(product_id)
items = cart_items.find_all_by_product_id(product_id)
product = Product.find(product_id)
if items.size < 1
ci = cart_items.create(:product_id => product_id,
:amount => 1,
:price => product.price)
else
ci = items.first
ci.update_attribute(:amount, ci.amount + 1)
end
ci
end
def remove(product_id)
ci = cart_items.find_by_product_id(product_id)
if ci.amount > 1
ci.update_attribute(:amount, ci.amount - 1)
else
CartItem.destroy(ci.id)
end
return ci
end
def update(product_id)
ci = cart_items.find_by_product_id(product_id)
ci.update_attribue(:amount => new_qty.to_i )
end
end
My cart_controller:
------------------------------
class CartController < ApplicationController
before_filter :initialize_cart
before_filter :authorize, :except => ["login"]
def authorize
return true if @c
flash[:notice] = "To place your order please login"
redirect_to :controller => "catalog"
end
def login
# examine the form data for "name" and "password"
pw,name = params[:customer].values_at(*%w{password name})
# Retrieve the customer record for the name and store it in a
variable ''c''
c = Customer.find_by_name(name)
# if such record exists, and it''s password matches the password
from the form
if c && Digest::SHA1.hexdigest(pw) == c.password
# start a session with the customer id
@session[''customer''] = c.id
if @cart.products.empty?
redirect_to :controller => "catalog"
else
redirect_to :action => "view_cart"
end
else
# otherwise report an error
flash[:notice] = "Invalid Login"
redirect_to :controller => "catalog"
end
end
def logout
@session[''customer''] = nil
redirect_to :controller => "catalog"
end
def index
end
def add
@product = Product.find(params[:id])
if request.post?
@item = @cart.add(params[:id])
flash[:notice] = "Added <em>#{@item.product.title}</em>
to
cart."
redirect_to :controller => "catalog"
else
render
end
end
def update
@product = Product.find(params[:id])
new_qty = params[:new_qty]
if request.post?
@item = @cart.update(params[:id], new_qty)
flash[:notice] = "Updated
<em>#{@item.product.title}</em>''s
quantity."
redirect_to :action => "view_cart"
else
render
end
end
def remove
@product = Product.find(params[:id])
if request.post?
@item = @cart.remove(params[:id])
flash[:notice] = "Removed
<em>#{@item.product.title}</em>"
redirect_to :action => "view_cart"
else
render
end
end
def clear
if request.post?
@cart.cart_items.destroy_all
flash[:notice] = "Cleared the cart"
redirect_to :controller => "catalog"
else
render
end
end
def view_cart
@page_title = "Shopping Cart for #{@c.name}"
@order = Order.new
if @cart.products.empty?
flash[:notice] = "Your shopping cart is empty! Please add
something to it before proceeding to checkout."
redirect_to :controller => ''catalog''
end
end
def checkout
@page_title = "Checkout"
@order = Order.new(params[:order])
@order.customer_ip = request.remote_ip
@order.customer_id = @session[''customer'']
populate_order
if @order.save
if @order.process
flash[:notice] = ''Your order has been submitted, and will be
processed immediately.''
session[:order_id] = @order.id
# Empty the cart
@cart.cart_items.destroy_all
redirect_to :action => ''thank_you''
else
flash[:notice] = "Error while placing order.
''#{@order.error_message}''"
render :action => ''view_cart''
end
else
render :action => ''view_cart''
end
end
def thank_you
@page_title = ''Thank You!''
end
def populate_order
for cart_item in @cart.cart_items
order_item = OrderItem.new(
:product_id => cart_item.product_id,
:price => cart_item.price,
:amount => cart_item.amount
)
@order.order_items << order_item
end
end
end
And _item.rhtml which part of the view_cart.rhtml:
----------------------------------------
<tr>
<td><%=h item.product.sku %></td>
<td><%= link_to item.product.title, :action => "show",
:controller => "catalog", :id => item.product.id
%></td>
<td><%= pluralize(item.amount, "pc", "pcs")
%></td>
<td>$<%= two_dec(item.price * item.amount) %></td>
<td><%= form_tag :controller => "cart", :action =>
"update", :id =>
item.product, :with => "new_qty" %>
<%= text_field_tag "new_qty", "", "size" =>
4 %>
<input type="Submit", value="Update"/>
<%= end_form_tag %>
</td>
<td><%= button_to "x", :controller => "cart",
:action => "remove", :id
=> item.product %></td>
</tr>
Now tell me the truth, how messy is my code? where are my mistakes?
Thanks,
Elle
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
You have a belongs_to :customer in your cart.rb, make sure you have a customer_id field integer in your carts table. Where is the initialize_cart method? On Oct 16, 5:29 am, elle <wazne...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> This is slightly different but still on the same subject. > So, I got the customer to log in, but.... he doesn''t have a cart that > belongs to him. Which means if another customer logs in, they see the > other''s cart. I want to associate the cart with a customer to also be > able to record the customer''s id in the orders table. but.... I don''t > know how to do that. > > Other problems that I have with my cart are: > 1) Update doesn''t happen > 2) checkout page suddenly doesn''t appear > > Will you have a look at how I can associate the cart with the logged > in customer? (And if you can at the other questions/problems) > > My cart.rb: > -------------------- > class Cart < ActiveRecord::Base > has_many :cart_items > has_many :products, :through => :cart_items > belongs_to :customer > > def total > cart_items.inject(0) {|sum, n| n.price * n.amount + sum} > end > > def add(product_id) > items = cart_items.find_all_by_product_id(product_id) > product = Product.find(product_id) > if items.size < 1 > ci = cart_items.create(:product_id => product_id, > :amount => 1, > :price => product.price) > else > ci = items.first > ci.update_attribute(:amount, ci.amount + 1) > end > ci > end > > def remove(product_id) > ci = cart_items.find_by_product_id(product_id) > > if ci.amount > 1 > ci.update_attribute(:amount, ci.amount - 1) > else > CartItem.destroy(ci.id) > end > return ci > end > > def update(product_id) > ci = cart_items.find_by_product_id(product_id) > ci.update_attribue(:amount => new_qty.to_i ) > end > > end > > My cart_controller: > ------------------------------ > class CartController < ApplicationController > before_filter :initialize_cart > before_filter :authorize, :except => ["login"] > > def authorize > return true if @c > flash[:notice] = "To place your order please login" > redirect_to :controller => "catalog" > end > > def login > # examine the form data for "name" and "password" > pw,name = params[:customer].values_at(*%w{password name}) > # Retrieve the customer record for the name and store it in a > variable ''c'' > c = Customer.find_by_name(name) > # if such record exists, and it''s password matches the password > from the form > if c && Digest::SHA1.hexdigest(pw) == c.password > # start a session with the customer id > @session[''customer''] = c.id > > if @cart.products.empty? > redirect_to :controller => "catalog" > else > redirect_to :action => "view_cart" > end > else > # otherwise report an error > flash[:notice] = "Invalid Login" > redirect_to :controller => "catalog" > end > end > > def logout > @session[''customer''] = nil > redirect_to :controller => "catalog" > end > > def index > end > > def add > @product = Product.find(params[:id]) > if request.post? > @item = @cart.add(params[:id]) > flash[:notice] = "Added <em>#...@item.product.title}</em> to > cart." > redirect_to :controller => "catalog" > else > render > end > end > > def update > @product = Product.find(params[:id]) > new_qty = params[:new_qty] > if request.post? > @item = @cart.update(params[:id], new_qty) > flash[:notice] = "Updated <em>#...@item.product.title}</em>''s > quantity." > redirect_to :action => "view_cart" > else > render > end > end > > def remove > @product = Product.find(params[:id]) > if request.post? > @item = @cart.remove(params[:id]) > flash[:notice] = "Removed <em>#...@item.product.title}</em>" > redirect_to :action => "view_cart" > else > render > end > end > > def clear > if request.post? > @cart.cart_items.destroy_all > flash[:notice] = "Cleared the cart" > redirect_to :controller => "catalog" > else > render > end > end > > def view_cart > @page_title = "Shopping Cart for #...@c.name}" > @order = Order.new > if @cart.products.empty? > flash[:notice] = "Your shopping cart is empty! Please add > something to it before proceeding to checkout." > redirect_to :controller => ''catalog'' > end > end > > def checkout > @page_title = "Checkout" > @order = Order.new(params[:order]) > @order.customer_ip = request.remote_ip > @order.customer_id = @session[''customer''] > populate_order > > if @order.save > if @order.process > flash[:notice] = ''Your order has been submitted, and will be > processed immediately.'' > session[:order_id] = @order.id > # Empty the cart > @cart.cart_items.destroy_all > redirect_to :action => ''thank_you'' > else > flash[:notice] = "Error while placing order. > ''...@order.error_message}''" > render :action => ''view_cart'' > end > else > render :action => ''view_cart'' > end > end > > def thank_you > @page_title = ''Thank You!'' > end > > def populate_order > for cart_item in @cart.cart_items > order_item = OrderItem.new( > :product_id => cart_item.product_id, > :price => cart_item.price, > :amount => cart_item.amount > ) > @order.order_items << order_item > end > end > > end > > And _item.rhtml which part of the view_cart.rhtml: > ---------------------------------------- > <tr> > <td><%=h item.product.sku %></td> > <td><%= link_to item.product.title, :action => "show", > :controller => "catalog", :id => item.product.id %></td> > <td><%= pluralize(item.amount, "pc", "pcs") %></td> > <td>$<%= two_dec(item.price * item.amount) %></td> > > <td><%= form_tag :controller => "cart", :action => "update", :id => > item.product, :with => "new_qty" %> > <%= text_field_tag "new_qty", "", "size" => 4 %> > <input type="Submit", value="Update"/> > <%= end_form_tag %> > </td> > <td><%= button_to "x", :controller => "cart", :action => "remove", :id > => item.product %></td> > </tr> > > Now tell me the truth, how messy is my code? where are my mistakes? > > Thanks, > Elle--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Should I start a session[:cart] and add the customer_id to it? would rails then see all the columns in the cart_items table? Or should I leave it as session[:customer]? On Oct 20, 6:33 am, "randomutterings..." <randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> You have a belongs_to :customer in your cart.rb, make sure you have a > customer_id field integer in your carts table. Where is the > initialize_cart method?--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I don''t think that would help. Your cart model has a before_filter called initialize_cart. I''m assuming that is what creates the cart and stores it in the database as I cannot see where that is happening. I would assume that initialize_cart should look something like this. def initialize_cart cart = Cart.new cart.customer_id = session[:customer_id] cart.save end On Oct 20, 1:50 am, elle <wazne...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Should I start a session[:cart] and add the customer_id to it? would > rails then see all the columns in the cart_items table? > Or should I leave it as session[:customer]? > > On Oct 20, 6:33 am, "randomutterings..." <randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > > > You have a belongs_to :customer in your cart.rb, make sure you have a > > customer_id field integer in your carts table. Where is the > > initialize_cart method?--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I should have posted my solution before.
I ended up creating a new [:customer] session at login as well as a
session{:cart].
In the carts table, I inserted the customer_id.
The relationships are:
class Customer < ActiveRecord::Base
has_many :orders,
:dependent => true,
:order => "created_at ASC"
has_one :cart
class Cart < ActiveRecord::Base
has_many :cart_items
has_many :products, :through => :cart_items
belongs_to :customer
Then when the customer logs off, I set:
session[:customer] = nil
session[:cart] = nil
Works great. The app remembers customer''s cart when he logs in next
time.
I got help with this as well (wish I knew the person''s name to give
credit).
Cheers,
Elle
On Oct 24, 1:49 am, "randomutterings..."
<randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:> I don''t think that would help. Your cart model has a
before_filter
> called initialize_cart. I''m assuming that is what creates the
cart
> and stores it in the database as I cannot see where that is
> happening. I would assume that initialize_cart should look something
> like this.
>
> def initialize_cart
> cart = Cart.new
> cart.customer_id = session[:customer_id]
> cart.save
> end
>
> On Oct 20, 1:50 am, elle
<wazne...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> > Should I start a session[:cart] and add the customer_id to it? would
> > rails then see all the columns in the cart_items table?
> > Or should I leave it as session[:customer]?
>
> > On Oct 20, 6:33 am, "randomutterings..."
<randomutteri...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > wrote:
>
> > > You have a belongs_to :customer in your cart.rb, make sure you
have a
> > > customer_id field integer in your carts table. Where is the
> > > initialize_cart method?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---