Store data from filled form - ruby-on-rails

Using restful_authentication and
before_filter :login_required, :only=> [:create]
on controller:
Is it possible to store data from form, and after user logged in, continue with 'create'?
So i mean:
User logged off and he see Somecontroller#new
Then he fill in the form
Then he press "Save"
As we have login_required, user now has to login.
After login the 'create' action continues, and user should be redirected to some path (which set on create action)
If no, how such system ca be done?
The main idea is smooth flow — so unregister user don't have to signup first, he can do that during "create" action.
Many thanks!

You can store the data with YAML in the session hash. After they login, you can then redirect back to the form action and retrieve values from session, or create the resource, or do whatever you need to do.

Related

Rails. Save pass parameter from action to action

For example, user visiting home with invitation link localhost:3000/home?invitation=invitation_token and I want to keep in params while user is browsing site till he visit registration page.
I know there is possibility to add params to link_to method but there is to many where I need to put this and it's not possible to predict user behavior.
But what I'm looking it's custom method what I will place in before_action what will check if there is params[:invitation] and pass it to next, unpredictable, method.
PS. I know that I can save to cookies, but this is not quite what I'm looking for.
You should save it in a session variable such as session[:invitation_token], otherwise you'll have to pass the param in every link. You can then use the variable directly such as:
before_action :check_token
def check_token
redirect_to registration_url unless session[:invitation_token]
end

Show page only once after sign up - Ruby on Rails

I have an app that is using Devise, I would like that after a user signs up, they are directed to a specific page, this page calls an API and saves the value from the API, I need this page to only be accessible or available after a user completes the sign-up form and clicks submit, and is then redirected to this page.
I do not want this page or URL accessible any other way but after sign-up, as the API will send a new value if accessed again. How can I accomplish this?
Once a user signs up they will be redirected to the page calling the API:
def after_sign_up_path_for(resource)
api_call_path ##path that can only be accessed after sign_up
end
The API is called and the response from the JSON data is automatically saved to the database once the page is opened, if the page gets opened again a new JSON response will be received with new data, which is what I would like to avoid.
So in a nutshell, my question is how can I restrict access to a specific path, and only make that path accessible if a user completes the sign-up form (devise) OR is there a way that I can run the code from the controller using a callback/filter after the user is created through the User model?
I was just busy with something similar. You do not need to direct the user to a page to run the code, you can just run the code that needs to be run after the user logs in the first time.
You need to create a Session Controller, and create a conditional statement that checks if the user has logged in previously:
#config/routes.rb
devise_for :users, controllers: { sessions: "sessions" }
#app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
if resource.sign_in_count == 1
##Do something awesome
else
root_path
end
end
end
As Emmanuel advised you can check futher info on the Devise Controllers.
Let's call the moment between after sign_up and showing the specific page - state A. So in the specific page controller you need to know - is the user in state A. You can achieve it by
1) saving to db (server side) that user is in state A after sign up and resetting state after showing specific page (you can do resetting triggered by client side to guarantee that page is showed).
2) saving to cookies (client side) after sign up then do as above.
Second solution is more clean in my opinion, but I do not know how strict is the rule to show only once
You can customize devise users controller by issuing
rails generate devise:controllers [scope]
Then customise UsersController such that after user is saved you can call your api code there
eg
def create
#user = ....
if #user.save
#user.call_api_method()
else
......
end
end
For more information check Configuring controllers

Landing Page for Age check in Rails App

I have built a marketing site for an alcohol brand and I need to check the user's age by adding a landing page before they can enter the main site. What is the best way to tackle the form, submit and validation functionality inside my existing rails app?
Should I just create a raw html form and use javascript?
Add a before_action to ApplicationController that checks if the verification has already taken place (i.e. if it is stored in a cookie, then check for the cookie, etc):
class ApplicationController
before_action :check_age
def check_age
# check if the user has already confirmed their age.
end
...
end
If it doesn't find this, then redirect the user to a controller action that renders a page with the age check form (i.e. AgeVerificationController#new)
Upon submit, set the cookie (or whatever you are doing to store this data), and redirect the user back to the page they were intending to visit (or kick them off the site if they say they are under age!)
You will need to include a skip_before_action on the controller you are using to handle the rendering and submission of the form, i.e.
class AgeVerificationController < ApplicationController
skip_before_action :check_age
...
end`
Using before_action is sometimes a bit of an anti-pattern if you start using it to do a lot of complex stuff, but in this case it is a fairly simple way of doing what you are looking to do.
even if you use javascript,you will need to store the age of the guest to help him out next time for a better user experience.So i will suggest you to save it along with the ip-address to recognise the guest,if you are not storing a unique parameter for login(such as email,mobile number etc).
Once you have the table ready to store this details...you have many options such as:-
first option is to that,before submit get the age of guest using jquery validation and pass it to the controller using form and store it.Use ajax for form submission so that
you can validate other elements as well
second option is to let the user visit the page and show a modal window popup in the middle,after five seconds when page has loaded by using settimeout to call ajax which in turn will call a controller method to render js file which will call a modal such as $(".myModal").show(); or render your own view to get user details such as:
$('#myModal').find('.modal-body').html("<%= escape_javascript(render(:partial => 'users/get_details')) %>");
$('#myModal').modal();

Devise: how to store a particular location, not necessarily the last location?

I'm wondering if I'm asking too much of Devise. I'd like to allow a visitor to fill out a form and then but then be required to sign up when they press the "submit" button. That's the easy part. My problem is that once the user is redirected to the sign up form and they fill it out, I can't get them redirected back to the original form so that that form can be submitted (but now with the user ID).
I've played around with the "after_sign_in_path_for(resource)" method in the application controller, but my problem is that after signup, the request.referer isn't the original form, it's the signup form. I thought about using a before_filter :store_location callback, but then I realized that it'll store the most recent location, which is the url for the signup form.
How do I set up devise that original form as the correct location to render after sign up?
P.S. This question comes from a related one, located here.
Try this make 2 method in ApplicationController which saves
the current url to the session, and another that redirects to the stored
url (which should have a default in case it can't find it). Then, in
pages which i want to bookmark for returning to (you might not want
someone to get sent back to some pages), then save the url.
EG in application.rb
def store_location
session['saved_location'] = request.request_uri
end
def redirect_to_back_or_default(default)
if session['saved_location'].nil?
redirect_to default
else
redirect_to session['return-to']
session['saved_location'] = nil
end
end
Then, in a page that you want the user to be able to go back to:
Then, just call
redirect_to_back_or_default('enter your chosen default url here, depending on context')
in after_sign_in_path_for(resource_or_scope) to send someone back.

Create first, login or signup later

Using Rails 3.
In usual app, a form only appears if the user is logged in. Then in the controller, we will run another check on authentication before we save the new record.
However, I want to show the form to everyone regardless if he's logged in. When the visitor submits the form with attachment, etc., it will then check if the user is logged in. If he isn't, then redirect him to login/signup page, and when he's completed that, only then the new record is saved.
I understand this can be achieved with the create and save, but can someone elaborate more on how to achieve this in a clearer explanation?
User submits form
Controller sees user is not logged in
Controller persists submitted form to the database
Controller sets cookie with id of new object
Controller redirects to login
User logs in
Controller retrieves persisted form information from database
Controller assigns object to user
Run a periodic job to clean old unclaimed form data.
Well, in the view you'd show the form always without any kind of login check. The tricky part here is to save the data the user has sent before he's redirected to the login.
One solution would be to save the post data in a cookie and then redirect the user to the same page after the login, triggering the create again
On the controller you'd do exactly as you described:
class ThingController
def create
if user_logged_in?
if cookie[:stuff]
# create the stuff from cookie and remove it
else
# create the stuff
end
else
# redirect him to login with a callback to this same place
end
end
end

Resources