Rails 3: How to tell if a user has visited a page before? - ruby-on-rails

I have a Rails app (using Authlogic for authentication) with a simple jquery animation that I only want to run once upon first page load. I know that the key is to check cookies or something to see if the user has visited the page before. Please forgive my n00bness, I know little to nothing about HTTP cookies or sessions.
So, what's the best way to see if a visiting user (even if they haven't logged in) is viewing a page for the first time?
EDIT: Ok, so I realize I wasn't being entirely clear.
I've spent hours looking at similar questions and reading the Rails API Docs for cookies and sessions and I still can't visualize how to implement a visited? function for each page in my site that will only be set to "true" after the user has visited the page the first time. I looked at the supposed "duplicate" question Rails Detect If User's Very First Visit and the respective answers and still can't figure it out.
Here's my "Pages" controller:
def home
#title = "Home"
end
def contact
#title = "Contact Us"
end
dd
And my jquery javascript that does a simple animation:
$(document).ready(function()
{
if (!$.cookie('visited')) {
$('.title .flying-text').css({opacity:0});
$('.title .active-text').animate({
opacity:1,
marginTop: "-150px",
}, 5000);
}
});
I only want it to show if the user HAS NOT visited the page before. I have no idea how to properly set a cookie in Rails, nor where to put it, nor how to make sure that the animation script can access that exact same cookie value. Can someone give me a hand?
~Dan

You can set a cookie like this:
cookies[:welcomed] = {:value => true, :expires => Time.now + 6.months}
and from jquery make a wee function
function readCookie(name) {
var nameEQ = name + "=", ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i += 1) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) === 0) {
return c.substring(nameEQ.length, c.length);
}
}
return null;
}
and call it #in js
if (readCookie('welcomed') == null){}

Ignore the cookie from Javascript.
Using the question referenced as a duplicate, use a permanent cooke and on the first run, set a class on your body from Rails (let's say first-run). Then, have your javascript check and see if body has class first-run. At that point, you can have javascript execute it's first run code.

Related

Mautic: How to tag users via a landing page?

I have created a campaign form in Mautic and used the manual copy feature to integrate it into my HTML landing page (this is a landing page I have made in HTML. It is not a Mautic landing page).
In Mautic, users are saved as a "contact". The contact has a field called "tags".
I would like to make use of the Mautic Tracking Javascript so I can send a value to this tag field from my HTML landing page.
Here is my code:
< script >
(function(w, d, t, u, n, a, m) {
w['MauticTrackingObject'] = n;
w[n] = w[n] || function() {
(w[n].q = w[n].q || []).push(arguments)
}, a = d.createElement(t),
m = d.getElementsByTagName(t)[0];
a.async = 1;
a.src = u;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'http://newsletter.smile.ws/mtc.js', 'mt');
mt('send', 'pageview', {
'tags': 'sunshine-book'
});
< /script>
To test it out, I submitted a test contact on my HTML landing page.
When I log-into Mautic and go to the contact page for the contact, the tag field is blank:
However, the tag does appear as an option in the tag menu:
How can I make it so the tag field is automatically filled with the tag?
The user renzof of the Mautic forum tested my code and it worked for him, but it didn’t work for me. I think I'm doing something wrong, but I can't figure it. Any ideas? Thanks!
The issue is the use of Http. The landing page uses https, but the code was using http (the s is missing), which is why it doesn't work. I updated all my code to use https and it worked.
there is actually nothing wrong with your code, I tested it and the only problem was browser blocking the request due to cors origin, other than that it worked fine.
But I have a hunch in case it doesn't work, i noticed the tags is actually plural and in mautic contact form it taken as array, so if cross domain issue isn't there at your end, can you try tags[] instead tags. However i think normal way should have worked.

Using a JSON user object for Authentication in AngularJS

So I've got an question about authentication and have been wondering how other people might handle this situation. I'm currently running an Angular app that is built on a Rails API.
So far for authentication I have a form that does a post to the Rails side which logs the user in and then sends them back to the Angular app on success. Once the cookie is set and the user is logged in, I'm able to access a user.json file which contains all the User information one might expect (Id, username, roles, rights, etc). Since verification all happens on Rails, if the user logs out then this information is removed. So the two states look like so...
Logged in
{
id: 99384,
name: "Username",
url: "//www.test.com/profiles/Username",
timezone: null,
rights: [ ],
roles: [
"admin"
],
}
Logged out
{
error: "You need to login or join before continuing."
}
So far I've seen all these millions of different ways to do auth for Angular, but it seems like nothing fits this type of method. So my question is, since the server is handling all of the verification, is there a way to just check if they user.json file is empty (displaying the error message) and if it is send the Angular app to the Rails login page? Is there really any point messing with Cookies, Tokens, etc when I can base it all on the JSON file?
You are already using cookies - the server is setting them. What you have done is a fairly standard way of doing things.
To check the json file, you can do something like this stub shows in your controller:
app.controller('AppControl', function($scope, $http, $location){
// Get the JSON file.
$http.get('/path/to/json/file')
.then(response){
if(response.data.error){
// redirect to login
$location.path('login');
}
else{
$scope.user = response.data;
// your app code here.
}
})
.catch(function (error){
// unable to reach the json file - handle this.
});
});
Of course, you should really move this out into a service so you can re-use it, and also cache the data, rather than getting the user every time you change route/page, but this gives you a vague idea.
EDIT Example factory:
.factory('User', function( $http ){
// Create a user object - this is ultimately what the factory will return.
// it's a singleton, so there will only ever by one instance of it.
var user = {};
// NOTE: I am assigning the "then" function of the login promise to
// "whenLoggedIn" - your controller code is then very easy to read.
user.whenLoggedIn = $http.get('user.json')
.then(function(response){
// Check to see if there is an error.
if (response.data.error !== undefined) {
// You could be more thorough with this check to determine the
// correct action (examine the error)
user.loggedIn = false;
}
else {
// the user is logged in
user.loggedIn = true;
user.details = response.data;
return user;
}
}).then; // <-- make sure you understand why that .then is there.
return user;
})
Usage in the controller
.controller('ExampleController', function($scope, User){
// It's handy to have the user on the scope - you can use it in your markup
// like I have with ng-show on index.html.
$scope.User = User;
// Do stuff only if the user is loggedin.
// See how neat this is because of the use of the .then function
User.whenLoggedIn( function (user){
console.log(user.details.name + " is logged in");
});
});
Because it's on the scope, we can do this in the html:
<body ng-controller="ExampleController">
<h1 ng-show="User.loggedIn == null">Logging in..</h1>
<h1 ng-show="User.loggedIn == true">Logged in as {{ User.details.name }}</h1>
<h1 ng-show="User.loggedIn == false">Not logged in</h1>
</body>
Here is an example on plunker where this is working.
Note the following:
If the user is/was already logged in, when you inject the service in the future, it won't check the file again. You could create other methods on the service that would re-check the file, and also log the user out, back in, etc. I will leave that up to you.
There are other ways to do this - this is just one possible option!
This might be obvious, but it's always worth saying. You need to primarily handle authentication and security on the server side. The client side is just user experience, and makes sure the user doesn't see confusing or conflicting screens.

Oauth return to same page after success/failure, How?

I have this in my config
callback = "http://xxx/oauth/facebook/callback"
successUri = "http://xxx/oauthCallBack/facebookSuccess"
failureUri = "http://xxx/oauthCallBack/facebookFailure"
and its working fine.
now the problem is, I have a sing in link in header which is shared amongst all pages, and when user click on it and authenticates using oauth, I want user to come back on same page from where he/she went for authentication.
How can this be done?
Any help much appreciated.
Thanks.
solved it myself.
Tried using referrer, but had some issues with it.
So
added hidden field with id=currentURL to form, and onLoad of body, populated this hidden field using javascript, eg:
function initParams() {
document.getElementById('currentURL').value = location.protocol + '//' + location.host + location.pathname;
}
and now I have currentURL in params in controller.

Rails search form doesn't work if page has another form

I have a search form in my navbar, so it's on all pages of the application. If i go to a page that has a form like the user's edit page or create a new post page the search doesn't work. How come?? How can i fix this??
EDIT (read comments)
// Make sure search form isn't blank
$("form.navbar-search").submit(function(){
var isFormValid = true;
$("input").each(function(){
if ($.trim($(this).val()).length == 0){
isFormValid = false;
}
else{
$(this).removeClass("highlight");
}
});
return isFormValid;
});
There could be a million reasons, and you haven't given us much to go on. What do you mean by "doesn't work"? Do you get JS errors in your browser console? Application errors in your Rails log?

how twitter passes query variables?

I notice that when I browse pages in Twitter. Instead of having some like twitter.com/home.php?var1=2&asjfaj...etc. (the most common way), the link is just Twitter.com/#home or twitter.com/inbox or twitter.com/followers. my guess is, they use sessions variables to pass information across pages/ links. is it a good way to do it? what are the pros and cons of using session or the url query to pass data across pages?
They're loaded via AJAX. The #home etc. in the URL allows bookmarking and browser history - if you go to http://twitter.com/#replies you get the replies page correctly, as their JavaScript code looks for document.location.hash's value and loads the right page.
Gmail also does this with the document hash, if you want another example.
ajax. lot of ajax!
EDIT
this is what I use to keep a history
<script>
function openOption(opened) {
if (!opened)
var selectedTab = document.location.hash;
else
var selectedTab = opened;
if (selectedTab != null && selectedTab.length > 0) {
selectedTab = (selectedTab[0] == '#') ? selectedTab.substring(1, selectedTab.length) : selectedTab;
if ($(selectedTab)) {
toggleLayer_on(selectedTab);
$(selectedTab).focus();
$(selectedTab).scrollTo();
}
}
}
openOption();
</script>

Resources