Reputation: 2211
I have been building a fashion e-commerce app that is quite far along the development cycle. It caters for both men's and women's products. At the moment, the user selects their gender at the start, and a gender_id is then passed into the user's session. This ID is then used in many of the queries throughout the site, and it determines which gender products the user is shown.
However, for SEO purposes, it is necessary that this information is shown in the URL and not the session. I do not want to have to pass a gender parameter for every link I do, like this...
http://www.shop.com/products?category=Jeans&gender=women
Essentially what I'd like to do is input the gender into the route, and have it stay. I have seen some sites where the URL is structured as follows...
http://www.shop.com/women/products?category=Jeans
How can I achieve this second URL structure with minimal impact to my controllers? Or perhaps there is a different way I could achieve my goal? Thanks!
Upvotes: 1
Views: 271
Reputation: 6138
Put it in your routes with a scope:
scope ':gender', :constraints => {:gender => /women|men/} do
resources :products
resources :cart
# other routes here
end
You can access gender with params[:gender]
. Any routes you place in that block will be scoped to a gender context.
Additionally, the gender scope will default to the current scope when generating urls. For example, if I browse to /men/products
and in that view I have a link to cart, if the url is generated with cart_path
the url will be /men/cart
. Once the select a gender you could write redirect them to the proper scoped path. The one problem I see is that you lose the unstopped routes for product and cart with this method.
Upvotes: 3
Reputation: 1012
Instead of doing a HTTP-GET, you may want to take a look at HTTP-POST which doesn't pass variables in the URL. For example, here is a simple HTML-page with one HETT-GET action and one HTTP-POST action:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1">
<title>HTTP example</title>
</head>
<body>
<h1>POST & GET example</h1>
<h2> Post form</h2>
<form method="post" action="post_get2.php">
text:<input type="text" size =40 name="name">
<input type=submit value="Submit Post">
</form>
<h2> GET form</h2>
<form method="get" action="post_get2.php">
text:<input type="text" size =40 name="name">
<input type=submit value="Submit Get" >
</form>
</body>
</html>
And here's a simple PHP-page (post_get2.php) that detects if you made a POST or GET action and prints it on the page:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1">
<title>HTTP example</title>
</head>
<body>
<h1>POST & GET example</h1>
<?
function stripFormSlashes($arr)
{
if (!is_array($arr))
{
return stripslashes($arr);
}
else
{
return array_map('stripFormSlashes', $arr);
}
}
if (get_magic_quotes_gpc())
{
$_GET = stripFormSlashes($_GET);
$_POST = stripFormSlashes($_POST);
}
echo ("<br/>");
echo ("<pre>");
echo ("POST info:\n");
print_r($_POST);
echo("</pre>");
echo ("<br/>");
echo ("<pre>");
echo ("GET info:\n");
print_r($_GET);
echo("</pre>");
if($_GET['name'])
{
$name = $_GET['name'];
}
echo($name);
?>
<p>
<a><input type="button" value="back" onclick="history.go(-1)"></a>
</p>
</body>
</html>
The great thing with POST is that it doesn't show what choices you made on your page. It just shows 'http://www.shop.com/products' all the time. Unlike GET 'http://www.shop.com/products?category=Jeans&gender=women'
Upvotes: 1
Reputation: 5239
You can pass in default GET
parameters to your routes. For example, the pattern below would match http://www.shop.com/women/products?category=Jeans
and automatically append gender=women
to your params hash.
get '/women/products' => 'Products#index', :gender => 'women'
get '/men/products' => 'Products#index', :gender => 'men'
You could also generalize this a little more by using a placeholder and a constraint in the route definition.
get '/:gender/products' => 'Products#index', :constraints => {:gender => /men|women/}
Upvotes: 2