Rails and Devise Gem: Avoiding store session for certain controller and action - ruby-on-rails-4

for certain ajax calls I want to skip store session. I use devise gem, when and how I can specify actions to exclude for update session?
regards

In the controller add:
after_action -> { request.session_options[:skip] = true }
As per the comments here:
:skip will not a set a cookie in the response nor update the session state

Related

How to get PayPal client-side info to Django?

I am using PayPal standard IPN payment solution in client side in my Django web app.
<body>
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
<!-- Include the PayPal JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: '88.44'
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(orderData) {
// Successful capture! For demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
});
}
}).render('#paypal-button-container');
</script>
</body>
everything works fine and I can access all the data through the details variable in the js code.
Now, i need to insert the details into django db, no api, simple model.
Tried many things, none worked.
I prefer not to use django-paypal because it doesn't have smart buttons (as far as i saw) and there is only option for "buy now button" and no credit / debit card.
how can it be done? or is there smart buttons for django-paypal package?
Thanks for the help!
How to get PayPal client-side info to Django?
Don't.
An integration that creates and captures payments with client-side JS functions is for very simple use cases. It should never be used if you need to do anything automated with the result, such as writing transaction results to a database.
Instead, API-based integrations exist for precisely this use case. Use the v2/checkout/orders API and make two routes (url paths) on your server, one for 'Create Order' and one for 'Capture Order'. You could use the Checkout-PHP-SDK for the routes' API calls to PayPal, or your own HTTPS implementation of first getting an access token and then doing the call. Both of these routes should return/output only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should verify the amount was correct and store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as reserving product or sending an email) immediately before forwarding return JSON to the frontend caller. In the event of an error forward the JSON details of it as well, since the frontend must handle such cases.
Pair those 2 routes with this frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server . (If you need to send any additional data from the client to the server, such as an items array or selected options, add a body parameter to the fetch with a value that is a JSON string or object)

Trigger action in Rails controller on model callback

I am trying to wrap my head around Live Streaming with Server-Sent Events in Rails. I have a Rake task listening for file changes which adds records to the database. Once added I would like to send a SSE to the frontend.
But, the model can't send events to the frontend, the controller is responsible for that. How do I tell my controller a new record was added to the database?
My (broken) solution so far: use an EventBus with an after_save callback in the model that announces the changes and asks the controller to listen for these messages:
require 'reloader/sse'
class SseController < ApplicationController
include ActionController::Live
def index
response.headers['Content-Type'] = 'text/event-stream'
sse = Reloader::SSE.new(response.stream)
EventBus.subscribe(:added) do |payload|
sse.write({ /* payload */ })
end
rescue IOError
ensure
sse.close
end
end
I think my request ends before the event is received meaning it will never end up in de subscribe block. Is this the right approach, if so, what am I missing?
SOLN 1: you can use rest_client gem to send a request to your controller in your after_save callback from model.
SOLN 2: Why dont you call a model method in your controller which creates the database records and then handles further action based on whether record was created or not

Rails 4 Devise 3 multiple New Registration pages

Using Rails 4 and Devise 3, I would like to have different registration pages based on the URL my user is given.
As an example, each of the following should be directed to a different view that acts as devise registration.
www.mydomain.com <-- current root to registrations#new
www.mydomain.com/user_type_1
www.mydomain.com/user_type_2
www.mydomain.com/user_type_3
How would I do this? I can copy app/views/devise/registrations/new.html.erb to capture the form but how would I make the routing work?
My routes are currently set up as such (I close each session so the user can sign up a friend, but that is not relevant to this question)
devise_scope :user do
authenticated :user do
root :to => 'devise/sessions#destroy', as: :authenticated_root
end
unauthenticated :user do
root :to => 'devise/registrations#new', as: :unauthenticated_root
end
end
So you want three different url paths that point to three different views, but you want the forms to all send their info to the same REST endpoint in the same controller (users#create)? That sounds simple. You have GET requests to get the html/erb files for each registration page (welcome#index, welcome#cool, welcome#coolest), and routes for each to send the GET request to the right controller action.
Then you set up the forms to all send their info to POST to users#new, and one route from there.
Does that make sense?

AngularJS + Django - csrf for separate apps

I have both a Django app and a Angular JS app hosted at different end-points. Obviously in order for XHR requests to work I need to set the csrf token within Angular, which is easy enough to do when Angular is served by Django, but not so much when independent.
Here is my code so far:
angular.module('App', [
'ngCookies',
])
.run(['$rootScope', '$http', '$cookies',
function($rootScope, $http, $cookies){
// Set the CSRF header token to match Django
$http.defaults.headers.post['X-CSRFToken'] = $cookies['csrftoken'];
// Bootstrap
$http.get('http://127.0.0.1:8000/test/').success(function(resp){
console.log($cookies['csrftoken']);
});
}
])
It seems that $cookies['csrftoken'] is always undefined, and I assume I have to retrieve this somehow but can't find any resources as to how this process works.
Can anyone point me in the right direction?
Cookies are only accessible on the same origin, so accessing from another domain won't share the CSRF Token through cookies, you're going to have to find another way to introduce the cookie (such as with Django's template tag).
Second, your example looks likes its trying to read a Cookie from the $http.get() call. The $cookie service collects Cookies from when the document is loaded (stored document.cookie) and the resulting cookies are not accessible from Ajax/XHR calls cross-domain.
You can use this:
app = angular.module("App", []);
app.run(function($http) {
$http.defaults.headers.post['X-CSRFToken'] = $.cookie('csrftoken');
});
where $.cookie comes from jQuery Cookie plugin.

How to save (temporarily) form data?

There are, say, 10 fields on page1 and hyperlink to page2. Also there is hyperlink on page2 to page1. I fill 5 fields and click on the hyperlink. Then I click on the hyperlink on page2 and return to page1. Is it possible to save filled fields and how?
Additional question: what if page2 modifies fields of page1. For example, creates new choice in multichoice field.
Django has implemented solution which allow to split forms on multiple web pages. It is called form wizard. Check here for the tutorial.
EDIT 1#
Check this questions up: Django Passing data between views, How do you pass or share variables between django views?
You can save filled fields using cookies via javascript after clicking on the link and before going to another page. For example it's possible to use this jQuery plugin jQuery-cookie. As documentations says:
A simple, lightweight jQuery plugin for reading, writing and deleting cookies.
Create session cookie:
$.cookie('the_cookie', 'the_value');
Create expiring cookie, 7 days from then:
$.cookie('the_cookie', 'the_value', { expires: 7 });
Create expiring cookie, valid across entire page:
$.cookie('the_cookie', 'the_value', { expires: 7, path: '/' });
Read cookie:
$.cookie('the_cookie'); // => 'the_value'
$.cookie('not_existing'); // => null
Delete cookie by passing null as value:
$.cookie('the_cookie', null);
Note: when deleting a cookie, you must pass the exact same path, domain and secure options that were used to set the cookie.