I am receiving ajax data in a rails controller.
my :updatedFunds comes in within the params, and I set the users' dollars column value equal to it's value-- but it isnt persisting!
def update_dollars
#user = User.find(params[:user_id])
new_dollars = params[:updatedFunds]
#user.dollars = new_dollars.to_i
#store to database?
end
Whats the last step here?
def update_dollars
#user = User.find(params[:user_id])
new_dollars = params[:updatedFunds]
#user.dollars = new_dollars.to_i
#user.save #store to database!
end
There are two methods that will work.
#user.update(dollars: new_dollars.to_i)
will change the attribute and record the change in the database.
You can also change it using the ruby setter method and then save to the database such as in the solution from #agripp. Both use ActiveRecord, an object-relational-mapper that Ruby on Rails just loves. The docs on it are awesome if you want to take a look.
you can use #user.save or if you use #user.save! then an exception will be raised it the save failed (eg. if validation failed)
Related
I think my question title is bit confusing. But what I am meaning to ask is I am creating my own authentication system using mobile. Just like devise comes with current_user to create a session, I want to know how can I achieve same on a different model.
I have a model called Commuter. It also has a id with it.
A record of commuter looks like this.
Commuter.last
<Commuter id: 867, phone_number: "9483942090">
I am trying to create a session after verfying the mobile number with my controller method as follows:
def verify
#commuter = Commuter.where(phone_number: params[:phone_number]).first
if (#commuter && #commuter.authenticate_otp(params[:otp],drift:300))
#commuter.auth_active = true
if #commuter.save
#Removed from session after verified it
session[:phone_number] = nil
session[:is_verified] = nil
#signed in commuter after verified it
sign_in(:commuter, #commuter)
flash[:notice] = "Your mobile no is verified."
end
else
flash[:alert] = "You have entered wrong otp.Please check again."
end
puts "#{current_commuter.phone_number}"
redirect_to root_path
end
I just a puts there to debug. So right now I am getting current_commuter as undefined local variable for obvious reasons I guess. So I wanted to know how can achieve this session based current commuter ?
You can save the Commuter id in the session as session[:cid] = 1 and create a method on your base controller like this
def current_commuter
#commuter ||= Commuter.find session[:cid]
end
helper_method :current_commuter
Currently I have a method called Visit and it basically adds on the the visit counter on Subscriber. This method gets triggered when a Subscriber enters their phone_number in a form. I simply want to make a active record query that will look something like this Susbcriber.find_by(params[id]).last.visit(this doesn't work BTW). Hopefully you get what I'm trying to do there, basically call the person that checked in last with their phone number. I'll show my code for clarity.
CONTROLLER METHOD:
def search
#subscriber = Subscriber.new
end
def visit
#subscriber = Subscriber.find_by(params[:phone_number])
if #subscriber
#subscriber.visit ||= 0
#subscriber.visit += 1
#subscriber.save
flash[:notice] = flash[:notice] = "Thank You #{#subscriber.first_name}. You have #{#subscriber.days_till_expired} until renewal"
redirect_to subscribers_search_path(:subscriber)
else
render "search"
end
end
There you can see the method that gets triggered when a Subscriber inputs their phone number. I simply want to call that person in the console.
CONTROLLER METHOD THAT IS NOT WORKING CURRENTLY:
def create
#subscriber = Subscriber.find(params[:subscriber_id])
#comment = #subscriber.comments.build(comments_params)
if #comment.save
flash[:notice] = "Thank you!"
redirect_to subscribers_search_path(:comments)
else
render "new"
end
end
This is the method that needs the new query to find the Subscriber that just entered their phone number.
Let me know if you need more info? Thank You!
I'm editing my answer to be more inclusive based on the comments. It seems like you've got a number of issues going on here and maybe you need to step back and rebuild this step by step. Consider test driving it and/or at least verify that you're getting what you expect using a debugging tool as you go along (byebug, pry, or even just judicious use of 'puts' and 'inspect').
The find_by method requires that you specify the attribute that you're trying to use to find the row by, as well as the value of the attribute
#subscriber = Subscriber.find_by(phone_number: params[:phone_number])
If you are using the model's primary key, just use find:
#subscriber = Subscriber.find(params[:id])
If you're calling a controller action, params should always be present. Try inspecting the params before moving on with any of the rest of the code. Make sure that you're getting what you expect. If not, evaluate your view code.
In rails i am trying to achieve something like :
#user = User.find(params[:id]) || current_user
ie: if User.find(params[:id]) doesn't find an existing record i want the #user to store the current_user
I think this might rather be a simple thing. But i just started off with ruby on rails.
Thanks in advance.
ptd is right - throwing an exception is Rails intention, because it's equivalent SQL where clause with passed id - and because of this Rails expected that record with such id exists. But instead of rescue-ing (I believe it's more pythonic way) I think you can use such code:
#user = User.find_by_id(params[:id]) || current_user
I'm trying to build a registration module where user can only register if their e-mail is already in an existing database.
Models:
User
OldUser
The condition on User will be
if OldUser.find_by_email(params[:UserName]) exists, allow user registration.
If not, then indicate error message.
This is really simple to do in PHP where I can just run a function to execute a mysql query. However, I couldn't figure out how to do it on Rails. It looks like I have to create a custom validator function but seems to be overkilled for a such simple condition.
It should be pretty simple to do. What have I missed?
Any pointer?
Edit 1:
This solution by dku.rajkumar works with a slight modification:
validate :check_email_existence
def check_email_existence
errors.add(:base, "Your email does not exist in our database") if OldUser.find_by_email(self.UserName).nil?
end
For cases like this, is it better to do validation in the model or at the controller?
you can do it as
if OldUser.find_by_email(params[:UserName])
User.create(params) // something like this i guess
else
flash[:error] = "Your email id does not exist in our database."
redirect_to appropriate_url
end
UPDATE: validation in model, so the validation will be done while calling User.create
class User < ActiveRecord::Base
validates :check_mail_id_presence
// other code
// other code
private
def check_mail_id_presence
errors.add("Your email id does not exist in our database.") if OldUser.find_by_email(self.UserName).nil?
end
end
I'd recommend starting with Devise.
See https://github.com/plataformatec/devise
Even if you have unusual needs like these, you can normally adapt it. Once you get to know it, it's extremely powerful, solid and debugged, and you can do all sorts of things with it.
Bellow is just an initial implementation .../app/controller/UsersController for User registration related actions.
def new
#user = User.new
end
def create
#user = User.new(params[:user])
#old_user = User.find_by_email(user.email)
if #old_user
if #user.save
# Handle successful save
else
render 'new' # and render some error message telling why registration was not succeed
end
else
# render some page with some sort of error message of 'new' new users
end
end
Update:
Check out the following resources for more info:
Ruby on Rails Tutorial
Rails: User/Password Authentication from Scratch, Part I/II
I have been trying to get my head around render_to but I haven't had much success.
Essentially I have controller methods:
def first
#I want to get the value of VAR1 here
end
def second
VAR1 = ["Hello", "Goodbye"]
render_to ??
end
What I can't figure out is how to accomplish that. Originally I just wanted to render the first.html.erb file but that didn't seem to work either.
Thanks
Edit: I appreciate the answers I have received, however all of them tend to avoid using the render method or redirect_to. Is it basically the case then that a you cannot pass variables from controller to controller? I have to think that there is some way but I can't seem to find it.
It is not a good idea to assign the object to a constant. True this is in a global space, but it is global for everyone so any other user going to this request will get this object. There are a few solutions to this.
I am assuming you have a multi-step form you are going through. In that case you can pass the set attributes as hidden fields.
<%= f.hidden_field :name %>
If there are a lot of fields this can be tedious so you may want to loop through the params[...] hash or column_names method to determine which attributes to pass.
Alternatively you can store attributes in the session.
def first
#item = Item.new(params[:item])
session[:item_attributes] = #item.attributes
end
def second
#item = Item.new(session[:item_attributes])
#item.attributes = params[:item]
end
Thirdly, as Paul Keeble mentioned you can save the model to the database but mark it as incomplete. You may want to use a state machine for this.
Finally, you may want to take a look at the Acts As Wizard plugin.
I usually don't have my controllers calling each other's actions. If you have an identifier that starts with a capital letter, in Ruby that is a constant. If you want to an instance level variable, have it start with #.
#var1 = ["Hello", "Goodbye"]
Can you explain what your goal is?
Have you considered using the flash hash? A lot of people use it solely for error messages and the like, it's explicitly for the sort of transient data passing you might be interested in.
Basically, the flash method returns a hash. Any value you assign to a key in the hash will be available to the next action, but then it's gone. So:
def first
flash[:var] = ["hello", "goodbye"]
redirect_to :action => :second
end
def second
#hello = flash[:var].first
end
way 1
Global variable
(fail during concurrent requests)
way 2
class variable
(fail during concurrent requests)
way 3
Stash the object on the server between requests. The typical way is to save it in the session, since it automatically serializes/deserializes the object for you.
Serialize the object and include it in the form somewhere, and
deserialize it from the parameters in the next request. so you can store attributes in the session.
def first
#item = Item.new(params[:item])
session[:item_attributes] = #item.attributes
end
def second
#item = Item.new(session[:item_attributes])
#item.attributes = params[:item]
end
way 4
The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed to the very next action and then cleared out.
def new
#test_suite_run = TestSuiteRun.new
#tests = Test.find(:all, :conditions => { :test_suite_id => params[:number] })
flash[:someval] = params[:number]
end
def create
#test_suite_run = TestSuiteRun.new(params[:test_suite_run])
#tests = Test.find(:all, :conditions => { :test_suite_id => flash[:someval] })
end
way 5
you can use rails cache.
Rails.cache.write("list",[1,2,3])
Rails.cache.read("list")
But what happens when different sessions have different values?
Unless you ensure the uniqueness of the list name across the session this solution will fail during concurrent requests
way 6
In one action store the value in db table based on the session id and other action can retrieve it from db based on session id.
way 7
class BarsController < UsersController
before_filter :init_foo_list
def method1
render :method2
end
def method2
#foo_list.each do | item|
# do something
end
end
def init_foo_list
#foo_list ||= ['Money', 'Animals', 'Ummagumma']
end
end
way 8
From action sent to view and again from view sent to other actions in controller.