Select optional command if Record not found - ruby-on-rails

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

Related

Assigning attributes, you must pass a hash as an argument

I've just upgraded from Rails 4.0.0 to 4.1.0.
Now I got this error:
When assigning attributes, you must pass a hash as an argument.
Here's the relevant part of my controller action:
# app/models/users_controller.rb
def create_user
#user = User.new()
#user.update_attributes(params[:user])
How can I solve this?
There are similar problems posted here on SO, byt my problem is different to the posted ones, because the hints which were given there aren't a solution.
If you want to allow params[:user] to be passed in empty, you can do this to prevent throwing an exception:
#user.update_attributes(params[:user]) unless params[:user].blank?
However, this might be a strange behaviour, since the controller action is meant to create a User.
In Rails, there is also a method present?, that is the inverse of blank?. You can use whichever one is more legible to you.
#user.update_attributes(params[:user]) if params[:user].present?

How do you 'save' data to your database in a rails controller?

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)

Writing into model using devise variable

I have model, and when i write into it, i'm using standart Model.create!(params[:somesymbol])
However in my form i have hidden field with current_user.id
current_user its variable from devise, which returns user that is logged. So when i create new record, i believe to user, that he didnt change value in hidden field. Is there any ways to avoid this, and write into model in some way like this
Model.create!(params[:somesymbol], user_id: current_user.id) ?
You can use :
Model.create!(params[:somesymbol].merge(user_id: current_user.id))
The user_id in params will be overridden by current_user.id (see doc)

type casts of params hash values

i have some troubles with understanding of "params" function in RoR.
let's assume that i have user Model.
the next code apperars in users controller and it's function is to process POST 'destroy' request. "current_user" function returns currently signed in user (an instance of User class I suggest). by comparing "current_user == params[:id]" 'destroy' function checks if user is trying to delete yourself
def destroy
if current_user == params[:id]
flash[:error] = "you cannot delete yourself!"
else
User.find(params[:id]).destroy
flash[:success] = "user deleted"
end
redirect_to(users_path)
end
So the problem is that chunk code works well. and I don't really understand why. My background is 3-years experience of C++/C# programming in university, so I presumed that such kind of comparsion should cause some type casts. In that case I think it would be User obj ---> string obj (OR string --> User???!!!!).
Although I have a lot of questions about how Rails manages to compare User class and string class, I could make myself comfortable with this.
But what if I want to optimize this task and explicitly compare just IDs: the one stored in params[:id] as a string(??) and the other in current_user["id"] hash.
first is of string type and second is of integer, am I wrong? because "current_user["id"] == params[:id].to_i" causes error, that implies that params[:id] returns instance of User class o_O
thanks!
first of all: get yourself a decent ruby book and read about it's dynamic type system and method execution. that should answer most of your questions that you have when you come from a language like c.
like the opperator overloading in c it's possible in ruby to implement custom behavior for things like ==. this is very easy in ruby, because == is just a method. that's how you could write comparisons for multiple types of classes, even though those are not symmetric anymore.
in your case, the code that you provided is just wrong. comparing current_user with params['id'] will always yield false.
you should write something like that:
user = User.find params[:id]
if current_user == user
redirect_to users_path, :error => "you cannot delete yourself!"
else
user.destroy
redirect_to users_path, :notice => "user deleted"
end
Your current_user variable should contain the id in integer or string format. Or maybe your user model has a to_s method defined for user instances. In this case when trying to convert the object to a string (for the comparison with a string), this method will be called which will be returning the id in string format.
You should print both the current_user variable as well as the params[:id] to be sure.
you should do this
if current_user.id.to_s == params[:id]
params[:id] is a string, and you should comparing it with the current_user's id , not current_user

Rails, Model Relationship Question

I have the following which works great:
#request_thread = current_user.request_threads.new(params[:request_thread])
And I have this which works great:
#requestable = find_requestable
#request_thread = #requestable.request_threads.new(params[:request_thread])
But if I try the 2nd line with:
#request_thread = #requestable.current_user.request_threads.new(params[:request_thread])
With the current_user I get the following error:
NoMethodError (undefined method `current_user' for #<Photo:0x10f95c828>):
app/controllers/request_threads_controller.rb:52:in `create'
app/middleware/flash_session_cookie_middleware.rb:14:in `call'
What did I mess up on here?
Thanks
UPDATE - with find_requestable
# http://asciicasts.com/episodes/154-polymorphic-association
def find_requestable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
The error message tells you exactly whats wrong: current_user doesn't exist for the #requestable object, whatever that is.
current_user is most likely a function inherited from ApplicationController, or at least that's usually where it lives. It usually returns a User object according to the current session. But that isn't a built-in part of Rails, so we need more information if you want me to go into greater detail.
#requestable looks like a polymorphic model instance so it wouldn't be aware of the current session.
There's a bit of Rails magic happening here that I think is confusing you.
Both #requestable.request_threads and current_user.request_threads are helper functions that have been generated by Rails on those objects to save you time by filtering results and filling in values automatically.
I think, by the code you have shown us so far, that you are trying to associate current_user with the new request_thread you are creating. In that case, you can simple merge that into the attributes manually. Since I don't know what your models look like I can only guess at the field names:
#request_thread = #requestable.request_threads.new( params[:request_thread].merge(:user => current_user) )
Like I said, the chainable functions are merely for convenience. For instance, you could write it this way instead:
#request_thread = request_thread.new(params[:request_thread])
#request_thread.requestable = find_requestable
#request_thread.user = current_user

Resources