How I Pass parameters from View to Controller In Ruby - ruby-on-rails

#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

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

Rails: Can't get test to pass on create action

I'm trying to make sure that people can't submit a create action if they submit an entry with an ID other than their own. For this, I have set up the test as following:
entries_controller_test.rb
def setup
#user = users(:thierry)
#other_user = users(:steve)
end
...
test "should redirect create action on entry with id that doesn't belong to you" do
log_in_as(#user)
assert_no_difference 'Entry.count' do
post :create, entry: { content: "Lorem Ipsum"*10, id: #other_user }
end
end
The outcome of the test is that Entry.count increases by one, therefore #user can create a post with ID #other_user (is the code correct to create an entry with ID of the other user?)
entries_controller.rb: My create action currently looks like this.
def create
#entry = #entries.build(entry_params)
if #entry.save
flash[:success] = "Your entry has been saved."
redirect_to root_path
else
flash.now[:danger] = "Your entry has not been saved."
render 'index'
end
end
The instance variable is being passed in to the action by calling before_action :correct_user on the action. Here's the correct_user method.
def correct_user
#entries = current_user.entries
redirect_to root_url if #entries.nil?
end
By the way, the create action is being called from the index page. I suspect the problem is indeed with authorization since my test can log in the user and create an actual entry.
Can anyone spot an issue?
Your code is only checking whether the current_user has some entries, but there is no validation on the user_id of the entry being submitted to the create action. Moreover, even if the user has no entries, the #entries variable will be [], which is not nil (so correct_user will never redirect to root). The correct check would have been #entries.empty?, but still the object would be created with an incorrect user, as long as the current_user already has some entries belonging to them.
The way I usually go about this is not to permit the user_id parameter (with strong_parameters), and by setting the ownership of new objects to the current_user. If you want to perform the check, your correct_user should look more like this:
def correct_user
unless current_user.id == params[:entry][:user_id]
flash[:alert] = "Some error message"
sign_out # This action looks like a hack attempt, thus it's better to destroy the session logging the user out
redirect_to root_url
end
end
I think this might work.
In your entries controller.
class EntriesController < ApplicationController
before_action :correct_user, only: [:edit, :update]
def correct_user
unless correct_user.id == params[:entry][:user_id]
else
redirect_to root_url
end
end
end

redirecting from another page taking info

So after the user signs up, i redirect them to my additional info page where i collect some more information. However, something is wrong with my design/implementation as rails is saying im missing users/create template
this is my users controller
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def additional_info
#user = User.new(user_addinfo)
if #user.save
redirect_to show_path
end
end
def create
#user = User.new(user_params)
if #user.save
# UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path
flash[:success] = "Welcome to InYourShoes!"
#return #user
else
render'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.permit(:year)
end
end
def show is the user profile page i want to show after redirecting to the additional_info page
def additional_info is just take additional info from the private method def user_addinfo
def create is the sign up process.
After entering the basic user info, it gets redirected to additional which is fine. but after the additional, it says im missing the users/create template, but my code i attempted to redirect to show_path and #usersshow, still doesnt work
any suggestions? sorry if this seems intuitive but Im new to rails.
I think your problem is in the additional_info method, as i said in the comment. What you're doing is:
creating a user
creating a session for the user (sign_in #user) - storing somewhere the user_id in the session
redirecting to your additional_info page
And here comes the problem. As the user is already signed in you don't have any need to create a new user with additional params. You should have some helper to retrieve the current signed in user (like current_user) and in additional_info method, just update it.
So your additional_info method would become something like:
def additional_info
user = User.find session[:user_id]
user.update params[:user]
redirect_to user_path #show action
end

How to build an update email function in Ruby on Rails?

I am trying to refactor the update action in my Rails action, so that users can change their own email address only after confirming it by clicking on a link that I send to them.
class UsersController < ApplicationController
before_filter :authorized_user
def update
current_email = #user.email
new_email = params[:user][:email].downcase.to_s
if #user.update_attributes(params[:user])
if new_email != current_email
#user.change_email(current_email, new_email)
flash[:success] = "Please click on the link that we've sent you."
else
flash[:success] = "User updated."
end
redirect_to edit_user_path(#user)
else
render :edit
end
end
def confirm_email
#user = User.find_by_email_token!(params[:id])
#user.email = #user.new_email
#user.save
end
private
def authorized_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
end
This function saves the new email to a database field new_email. email will be replaced only after the user has confirmed his new_email through a URL:
class User < ActiveRecord::Base
def change_email(old_email, new_email)
self.email = old_email
self.new_email = new_email.downcase
self.send_email_confirmation_link
end
end
The code partially works, but I wonder if there's a more elegant way to do this, maybe by using an after_save callback or at least moving more code to the model.
What would be the best way to do this?
Thanks for any help!
P.S. Please don't suggest to use Devise for this. I really want to build my own authentication system here :-)
I would advise you against using ActiveRecord callbacks to perform business logic: ActiveRecord models should only be a thin wrapper around the database persistence layer.
Look at how the controller code can be changed:
def update
if UpdatesUserCheckingEmail.new(#user, params[:user], flash).execute!
redirect_to edit_user_path(#user)
else
render :edit
end
end
All the business logic is performed by an external object, which encapsulates all your business logic (which you can put in app/services/updates_user_checking_email.rb)
class UpdatesUserCheckingEmail
attr_reader :user, :user_params, :flash
def initialize(user, user_params, options = {})
#user = user
#user_params = user_params
#flash = options[:flash]
end
def execute!
if user.update_attributes(user_params)
if new_email != current_email
user.change_email(current_email, new_email)
flash[:success] = "Please click on the link that we've sent you."
else
flash[:success] = "User updated."
end
end
end
private
def current_email
user.email
end
def new_email
user_params[:email].downcase.to_s
end
end
I'd also advise you to move the logic which sends the email out of the ActiveRecord model and inside a dedicated service object. This will make your app much more easier to change (and to test) in the future!
You can find a lot more about these concepts here: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
I think you should not check current_email and new_email after update in database because it should before the database update. Another one is you are sending link to user after updating email to the database. So, that could not meet your goal i.e. "email will be replaced only after the user has confirmed his new_email through a URL." You should create new action for updating user email or you should write logic for updating user email when user get email of "reset email" in update action of UserController. Following is something simple approach to resolve your problem:
class UsersController < ApplicationController
def send_email_rest
#user.change_email(#user.email, params[:new_email]) if params[:new_email].present?
end
def update
if #user.update_attributes(params[:user])
#stuff you want to do
end
end
end
Hope that helps!!!

undefined method `session' for ApplicationController:Class

I am practicing with rails and I was in the topic of "session" and I get the message
"undefined method `session' for ApplicationController:Class"
please help me
this is the code
*(controller aplication)
class ApplicationController < ActionController::Base
session :session_key => 'ruby_cookies'
end
*(controller when I want to create the cookies)
class RegistroController < ApplicationController
def index
end
def login
if request.post?
p_user = User.new(params[:user])
user = User.find_by_nombre_and_password(p_user.nombre, p_user.password)
if user
session[:user_id] = user.id
flash[:notice] = "se ha identificado correctamente"
redirect_to home_url
else
flash[:notice] = "se incorrecto psps"
redirect_to login_url
end
end
end
def logout
session[:user_id] = nil
flash[:notice] = "adios sayonara"
redirect_to home_url
end
end
Your code is really hard to read, but the issue is probably related to this line where it looks like it's trying to call a method "session" and pass it a key/value pair.
session :session_key => 'ruby_cookies'
This doesn't appear to be within any sort of controller action. Normally you would set a session value with session[:my_value] = 'value' and read it with session[:my_value], just like a normal hash.
Your code in ApplicationController doesn't belong there. It belongs in a configuration file, for example config/environment.rb, where it would read something like this:
config.action_controller.session = {
:session_key => 'ruby_cookies'
}
See http://guides.rubyonrails.org/configuring.html for much more detail.

Resources