Rails 4: Change Database Values - ruby-on-rails

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])

Related

NoMethodError (undefined method `search=' for #<Profile:0x000000016d1fb8>) in production mode but not in development mode

My web app works perfectly in development mode but in production mode i cant even log in. Once i log in there is an error which is:
NoMethodError (undefined method `search=' for #<Profile:0x000000016d1fb8>).
The same error appears if i sign up and then create my profile. How do I solve this? I am working with ruby on rails in aws cloud 9 environment and am trying to deploy to heroku. I am using sqllite3 for development and postgressql for production.
this is my profilescontroller.rb
class ProfilesController < ApplicationController
before_action :authenticate_user!
before_action :only_current_user
# GET to /users/:user_id/profile/new
def new
# Render blank profile details form
#profile = Profile.new
end
# POST to /users/:user_id/profile
def create
# Ensure that we have the user who is filling out form
#user = User.find( params[:user_id] )
# Create profile linked to this specific user
#profile = #user.build_profile( profile_params )
if #profile.save
flash[:success] = "Profile Created"
redirect_to user_path(id: params[:user_id] )
else
render action: :new
end
end
def edit
#user = User.find( params[:user_id] )
#profile=#user.profile
end
def update
#user = User.find( params[:user_id] )
#profile = #user.profile
if #profile.update_attributes(profile_params)
flash[:success] = "Profile Updated."
#redirect to their profile page
redirect_to root_path
else
render action: :edit
end
end
private
def profile_params
params.require(:profile).permit(:first_name, :last_name, :avatar, :age, :gender, :city, :collegeemail, :minimumage, :maximumage, :genderpreference, :collegepreference, :search)
end
def only_current_user
#user = User.find( params[:user_id] )
redirect_to(root_url) unless #user == current_user
end
end
It sounds like the table for the Profile model is not the same in production as in development. Specifically, it seems that the search column is missing, causing Profile not to have a getter and setter for search.
I assume you have forgotten to run a migration in production, which adds the search column to the table of the Profile model.
Above error comes whenever we dont have the specific column present in the table. Make sure we have run the migration on the production or just have a look in to schema.rb file and look for column "search" in profile table.

How to prompt user to sign in after filling out form while keeping form data with rails

I have a Rails 4 App an Order Model where a user fills out a form for necessary data for price calculations etc. What I want is that they are prompted to sign in (with DEVISE gem) at the end of step_3 and are routed to a payment section but they can store their form data from the Order Model that the user has previously filled out, this data being the order form data before they signed in.
Main Issues:
Redirecting them after sign in mid way through process using devise
Saving the form data and associating it with the current user immediately before routed to the payment section
the Order.find_by section. What do I find the order by?
Background:
Rails 4
PostgreSQL
Devise Gem
class OrdersController < ApplicationController
before_action :authenticate_user!, :except => [:step_1,:process_step1,:step_2a,:process_step_2a, :step_2b, :step_2c, :step_3]
def step_1
#order = Order.find_by id: session[:order_id]
if #order.nil?
#order=Order.new
#order.save!
end
end
def process_step1
order = Order.find_by id: session[:order_id]
order.update_attributes(order_params)
if (order.building == 'Residential') || (order.building == 'Commercial' )
redirect_to step_2a_path
elsif (order.building == 'Commercial + Parking') || (order.building == 'Residential + Parking')
redirect_to step_2b_path
else
redirect_to step_2c_path
end
end
def step_2a
#order = Order.find_by id: params[:session_id]
end
def process_step_2a
order= Order.find_by status: 'cart'
# , user_id: current_user.id
order.update_attributes(order_params)
if order.save
redirect_to step_3_path
end
end
def step_2b
#order= Order.find_by status:'cart'
# , user_id: current_user.id
end
def process_step_2b
order= Order.find_by status: 'cart'
# , user_id: current_user.id
order.update_attributes(order_params)
if order.save
redirect_to step_3_path
end
end
def step_2c
#order= Order.find_by status:'cart'
# , user_id: current_user.id
end
def process_step_2c
order= Order.find_by status: 'cart'
order.update_attributes(order_params)
if order.save
redirect_to step_3_path
end
end
def step_3
#order= Order.find_by status:'cart'
# , user_id: current_user.id
end
def process_step_3
order= Order.find_by status: 'cart', user_id: current_user.id
order.update_attributes(order_params)
if order.save
redirect_to payment_path
end
end
def payment
#order= Order.find_by status:'cart', user_id: current_user.id
end
First off you should really refactor you routes. With that structure your application is going to get exponentially more confusing to navigate the larger it grows, and will make it practically impossible for anyone else to work on it/help you with debugging. Take a look at this guide on RESTful routing to learn more.
As for you issue, you can store their form data in one of the rails temporary storage mechanisms (I'd recommend a session variable) while they're logging in then redisplay it after they finish
There is a callback after_sign_in_path_for, you can add it in your ApplicationController. Usage is here
2,3. Continue to use session[:order_id]. Can't figure out why do you use find_by status: 'cart' and Order.find_by id: params[:session_id]. Check this url to save old session after log in.
Personally I do not recommend this method and I think it's better to bind order id to some secure random generated value stored in cookie.

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

Storing Params in a Session with Nested Resource

I am using Rails 4.
I have subarticles nested into articles. I am storing all of the form data from subarticles in a session when a user needs to create an account before submission.
Here is what I am using (subarticles_controller):
def create
if current_user.nil?
session[:subarticle] = params
redirect_to new_user_session_path
end
Then after the user signs up, it creates the subarticle with the stored params using
if session[:subarticle].present?
#subarticle = current_user.subarticles.create(session[:subarticle]["subarticle"])
session[:subarticle] = nil
flash[:notice] = "Awesome, you are logged in and your answer is undergoing review."
edit_user_registration_path
end
I am having trouble, however, saving the article_id in which the subarticle is created under. Can someone point me in the right direction to doing this?
A better approach could be to save the (sub)articles created by guest users in the database.
class SubArticlesController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy]
# ...
def create
#subarticle = Article.new(article_params) do |a|
if current_user
a.user = current_user
else
a.token = SecureRandom.hex
end
end
if #subarticle.save
if #subarticle.user
redirect_to #subarticle
else
session[:after_sign_in_path] = edit_article_path(#subarticle, token: #subarticle.token)
redirect_to new_user_session_path, notice: 'Please sign in to finalize your article.'
end
else
render :new
end
end
def edit
if #subarticle.user.nil? && #subarticle.token != params[:token]
redirect_to root_path, alert: 'You are not authorized.'
end
flash[:notice] = 'Please press save again to publish your post.' unless #subarticle.user
render :edit
end
def update
# The #subarticle.token should be included in the edit form
unless #subarticle.user && #subarticle.token == params[:sub_article][:token]
# let the current user claim the article
#subarticle.user = current_user
end
if #subarticle.update(article_params)
redirect_to #subarticle
else
render :edit
end
end
private
def set_article
#subarticle = Article.find(params[:id])
end
def sub_article_params
params.require(:sub_article).permit(...)
end
end
So here we we instead give the user a link to the edit page for the article where he/she can "finish" the article after logging in.
Since a malicious user could potentially "steal" unclaimed articles by guessing the id and entering the edit url we add a random token which we store in the database with the article and add to the url. Not 100% foolproof but at least better.
To make this work you will also need to add a token field to your form:
<%= form_for(#subarticle) do |f| %>
...
<%= f.hidden_field :token %>
...
<% end %>
The reason you might want to consider this is because session storage is often memory based and if you have a large amount of traffic storing the entire params hash in the session will exhaust the server memory. Also you should reset the session before logging a user in or out to avoid session fixation.
We do have a few issues though - first we don't want to accumulate a bunch of "unclaimed" articles if the user (or a bot) never logs in. The easiest way to do this is to setup a cron job to delete articles over a certain age without an associated user.
You would also want to filter any articles without a user from you show/index action.

Nested form validation rails 3.2

I have a job and user(devise) form in the same view. When I am trying to submit with errors in the user fields it gives me an exception page with the validation messages. Submitting errors in the job fields works fine!
job_controller.rb
def new
#job = Job.new
if !current_user
#job.user = User.new
end
respond_to do |format|
format.html # new.html.erb
end
end
def create
#types = Type.all
#categories = Category.all
#job = Job.new(params[:job])
#if not logged in creates a user and sign in
if !current_user
#user = User.new(params[:job][:user_attributes])
else
#user = current_user
end
#job.user_id = #user.id
respond_to do |format|
if #job.save
if !current_user
sign_in(:user, #user)
end
format.html { redirect_to #job }
else
format.html { render action: "new" }
end
end
end
job.rb
attr_accessible :user_attributes, :description, :name ....
belongs_to :user
accepts_nested_attributes_for :user
Thanks!
That becuase you are calling, #user.save! which will generate an exception. Also doing it this way won't put the job in the same transaction as User. What you want are nested_attributes:
class Job < ActiveRecord::Base
accepts_nested_attributes_for :user
end
If the user is logged in, don't show that part of the form and filter those params.
See more in the Rails documentation here http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
EDIT:
Simplify your controller code, since you're using nested attributes you no longer need to manually create a user.
#if not logged in creates a user and sign in
if !current_user
#user = User.new(params[:job][:user_attributes]) # this is no longer needed
else
#user = current_user
end
#job.user_id = #user.id # this is redundant
To something more like:
# if logged in, manually assign the user (also you may want to reject any user attributes)
#job.user = current_user if current_user

Resources