How to send data from one model/ controller to another in Rails - ruby-on-rails

Not sure how to achieve this:
User enters email on page 1
On page 2, User doesn't have to enter email again, because it has persisted (again across controllers/ models)
Yet another way of saying it using code snippets below:
User enters email "test#gmail.com" in signups/new
Email is posted to signups/create, so now the model signups has one new row of data with "test#gmail.com"
User redirected to requests/new
On requests/new, I'd like the same email that the user just signed up with to be immediately accessible, i.e., #requestrecord.email = "test#gmail.com" in the new action, so User doesn't have to re-enter it and post to requests/create
Signup Controller code
def new
#signup = Signup.new
end
def create
#signup = Signup.new(signup_params)
if #signup.save
redirect_to new_request_path
else
render new_signup_path
end
end
Request Controller code
def new
#requestrecord = Request.new
end
def create
#requestrecord = Request.new(request_params)
end

You could just set the user's email in a session variable:
def create
#signup = Signup.new(signup_params)
if #signup.save
session[:user_email] = #signup.email
redirect_to new_request_path
else
render new_signup_path
end
end
and then you can use it as needed with session[:user_email] in your Request controller.

Related

Rails 4: Change Database Values

I'm fairly new to rails and struggling on changing database values after the user successfully paid via stripe. Additionally after paying, it somehow redirects me everytime to '/subscriberjobs/1' which doesn't exist. Instead it should direct to the root_path of the application.
Here is what I've got:
Routes
resources :subscriberjobs
resources :jobs
Jobs Controller
def new
if current_user
#job = current_user.jobs.build
else
redirect_to new_user_session_path
end
end
def create
#job = current_user.jobs.build(job_params)
if #job.save
redirect_to '/subscriberjobs/new'
else
render 'new'
end
end
Subscriberjobs Controller (Here is what doesn't work!)
class SubscriberjobsController < ApplicationController
before_filter :authenticate_user!
def new
end
def update
token = params[stripeToken]
customer = Stripe::Customer.create(
card: token,
plan: 1004,
email: current_user.email
)
Job.is_active = true # doesn't work
Job.is_featured = false # doesn't work
Job.stripe_id = customer.id # doesn't work
Job.save # doesn't work
redirect_to root_path # doesn't work
end
end
Please tell me if you need additional information. Every answer is very appreciated. Thanks!
Send saved job id to subscriberjobs/new as a param. You can keep hidden field which will have value job_id in subscriberjobs/new html form, which will call your SubscriberjobsController#update method. There access it using params.
In JobController #create
redirect_to "/subscriberjobs/new?job_id=#{#job.id}"
In your SubScribeJob form
hidden_field_tag 'job_id', params[:job_id]
In your SubScribeJobCotroller
#job = Job.find(params[:job_id])

How I Pass parameters from View to Controller In Ruby

#app/controllers/sessions_controller.rb
class SessionController < ApplicationController
def new
#session = Session.new
end
def fetch
##user = User.session(params [:user])
redirect_to "http://www.google.com"
end
def create
emai = params[:email]
puts emai
user = User.find_by(:email => session[:emai])
#user = User.find_by (params [:email])
#user = User.find_by email: 'abc#xyz.com'
#user = User.find_by(params[:Email])
#if (session[:Email] = user.email)
if (user)
redirect_to "http://www.yahoo.com"
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
redirect_to "http://www.google.com"
end
#redirect_to "http://www.yahoo.com"
end
end
every time i execute my view i get redirected to google.com even though i pass the parameters.
Edit by R Peck:
My logic should send people to Yahoo if the params are set, but still sends to Google, how can I fix this?
Try:
user = User.find_by(:email => params[:sessions][:emai])
You are not getting the value of email if you only call params[:email] you should call parent first before calling the child params[:sessions][:email].
Several things wrong with your code.
Here's what I'd write:
#app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def new
#session = Session.new
end
def create
email = params[:sessions][:email]
user = User.find_by email: email
url = user ? "google" : "yahoo"
colour = user ? "valid" : "invalid"
notice = user ? "You signed up successfully" : "Your form is invalid"
redirect_to "http://#{url}.com", notice: notice, color: colour
end
private
def session_params
params.require(:session).permit(:session, :params)
end
end
OOP
I think this may be a little advanced but I'll write it anyway, for my own benefit.
Rails is object orientated (it's built on Ruby which is an OOP language). This means that each time you create/call a controller, it should be centered around objects.
A good example for you would be the Devise controllers.
This has a sessions_controller which essentially allows you to CRUD (Create Read Update Destroy) a session. This is the correct way to use a controller.
Your implementation seems to be dealing with a user, rather than a session, and as such you'd be best using a users_controller to fix it:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new
#user.save
end
end
Having said that, it does seem that you're probably going to resolve the issue to make it so that you can use the User to build a new session.
I guess it's best to remember that you have to ensure you're able to appreciate a good structure for your application

Authorizing users so they can only view their own objects

I have a user model and users have many patients. A user should only be able to view their own patients.
What's the best way to implement this?
Here is my original patients show action. This allows any logged in user to view any patient:
def show
#patient = Patient.find(params[:id])
#assessments = #patient.assessments
end
I can switch it to below, but then I get an error page (patient id not found) and I'm not sure if this is the best way to handle it:
def show
#patient = current_user.patients.find(params[:id])
#assessments = #patient.assessments
end
What's the best approach for handling simple authorizations like this? Nothing fancy, just want users to only be able to view and edit their own stuff.
Edit
Here is the error I get when trying to access another user's patient:
Couldn't find Patient with 'id'=27 [WHERE "patients"."user_id" = ?]
Instead, I'd prefer to show the user a flash message saying they're not authorized.
def show
#patient = Patient.where(id: params[:id],user_id: current_user.id)
#assessments = #patient.assessments
end
here #pateint will give all the patient of the current login users & #assessments will give asssessments related to patients.
You could use find_by, which does not throw an error if nothing is found.
def show
#patient = Patient.find_by(id: params[:id])
if #patient && #patient.user == current_user
#assessments = #patient.assessments
elsif #patient.user != current_user
flash.now[:danger] = 'You are not authorized!'
else
flash.now[:danger] = 'The patient was not found'
end
end
Then you should test in your view if the patient exists.
That looks a little messy and repetitive, however, so you could refactor, for example by making a new function. Put this in the model patient.rb, and if current_user comes from application_helper, you may have to include ApplicationHelper.
authorized?
self.id == current_user.id
end
Now the conditional of the first code example could be like this:
if #patient
#assessments = #patient.assessments
unless #patient.authorized?
flash[:danger] = 'You are not authorized!'
# here, redirect the user away from the show page
end
else
flash.now[:danger] = 'The patient was not found'
end

Issue with Rails routes and models

I have 2 models - User model and Profile model. I have setup the relationship as follows:
class User
has_one :profile
end
class Profile
belongs_to :user
end
I have a profiles controller with 4 actions - new create edit and update. Once the User signs up or logs in he is redirected to the New action in the Profiles controller. From here how do I create a profile for that user? Specifically what should I have in my New action and Create action. Right now the route for the new action is just profiles/new which doesn't capture the Users params. I am trying to do this but its failing.
Profiles Controller
def new
#user = User.find(params[:id])
#profile = #user.build_profile
end
def create
#profile = current_user.build_profile(params[:profile])
if #profile.save
redirect_to current_user
else
render new
end
end
the new action in the profile controller doesn't need to get the id of the user from the params.
So your controller would be like this
def new
#user = current_user
#profile = #user.build_profile
end
def create
#profile = current_user.build_profile(params[:profile])
if #profile.save
redirect_to current_user
else
render new
end
end
actually sending the id of the user to the new action could be a security hole as I could send the id of another user and create a profile for some other user in the system, which shouldn't be allowed.
You should not be using User.find(params[:id] in your new action.
Just like in your create action below, you should be getting the User through current_user.
Is there more to the problem than not being able to properly fetch the User?

I would like to do is have the login and signup form as a single form

I am using devise for authentication.
If the email already exists it logs the user in.
If the email does not exist then it creates a new user using those credentials.
there should be only one submit button and a field for email and password.
that is possible for that have to write condition for that in your controller
for example
def create
#user = #user.find_or_create_by(params[:user])
....
....
end
or
def create
#user = User.find(params[:user])
unless #user.present?
#user = User.new(params[:user])
if #user.valid?
...
else
...
end
end
end
or # for devise - in registration controller
def create
#user = User.find_by_email(params[:user][:email])
if #user.present?
sign_in(resource_name, resource)
else
if resource.save
if resource.active_for_authentication?
...
...
else
...
...
end
else
...
...
end
end
end
You create a form for user_session that goes to create action.
On the server side somewhere, you call this from your create action. I would put in a method of UserSession.
if User.find_by_email(email)
# check credentials
else
# create user
end

Resources