How can i update an object properly? - ruby-on-rails

how can i update a object properly? my attempt is not working i am getting an error:"#<ArgumentError: wrong number of arguments (given 1, expected 2)>",
this is my endpoint:
def update
#car = Car.find(params[:id])
#car.update_attribute(car_params)
render json: #car
end
and the params are like this:
def car_params
params.require(:post).permit(:title, :description)
end
this is my query in postman
put->http://localhost:3000/cars?id=9
{"title":"new title", "description":"descriptions000"}

I suggest update! in cases like this.
def update
#car = Car.find(params[:id])
#car.update!(car_params) # <-
render json: #car
end
update! is nice because it will raise an error when validations fail. If you use update (no bang) or update_attributes, you might silently fail to update anything, which may lead to confusing behavior.

Here you are trying to use update_attribute instead update_attributes.
For update_attribute
# Syntax
update_attribute(name, value)
# example
update_attribute(:title, 'Ferrari')
For update_attributes
# Syntax
update_attributes(attributes)
# example
update_attributes(title: "Ferrari", description: "This is my Car"})
Please change your endpoint as below
def update
#car = Car.find(params[:id])
#car.update_attributes(car_params)
render json: #car
end
Please refer to update_attributes.
I hope this will help you.

Related

ruby on rails undefined method 'valid' when using update

I am using the same commands that I previously used in successful projects but now I suddenly can't validate any updates to the object(in this case, User). Everything else works fine but any attempt to check my validations for an update results in this error-
'undefined method `valid?' for # '
It is finding successfully finding the user and if I skip the .valid? statement then it will update, just without checking any of my model validations. I recently switched from SQLite to PostgreSQL, I am not sure if that's giving me the problem. I am new to Ruby but I couldn't find anything on this specific problem.
Please let me know if I should include the entirety of my controller or any of my model but as my create works fine, I feel like all the relative code is just in this little section-
class UsersController < ApplicationController
def update
#user = User.find(params[:id])
puts "#Is this working???!! #{#user}" ///prints #Is this working???!! #<User:0x00000001f24468>
#user = User.update(user_params)
if #user.valid?
redirect_to "/users/#{#user.id}"
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password)
end
Your problem is here:
#user = User.update(user_params)
If you put in your check after, you would see: #Is this working???!! true, which would ironically enough inform you that it's not working.
That's because User.update(user_params) returns true or false depending on whether it is successful or not. This means your #user object is now simply either true or false, which you can't call valid on.
If you want to handle successfully updating / failing to do so, try:
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to "/users/#{#user.id}"
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end
ActiveRecord update(id, attributes)
Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.
Then, you can do this checking if #user.update(user_params)
def update
#user = User.find(params[:id]) //Find user
if #user.update(user_params) // Update user if validations pass
redirect_to "/users/#{#user.id}"
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end
Or, you can call the update method directly in your model class, but the first argument must be the user ID
User.update(params[:id], user_params)
Thank you both for your quick answers. I was replying to tell you that I already tried that and it worked but did not validate. But as two of you told me the same thing, I decided to test it out again and the validations did indeed work this time so thank you (although I definitely have a user with an email of 'asdf' from last time).
Intestering enough, I found another answer although I have no idea why it worked. I added another puts statement after the update and realized my object had been converted to an array so I came up with this other (worse) alternative answer-
def update
#user = User.find(params[:id])
puts "#Is this working???!! #{#user}"
#user = User.update(user_params)
puts "#Is this working???!! #{#user}" ///prints #Is this working???!! [#<User id: 2, name: "James Dean", etc..>]
if #user[0].valid?
redirect_to "/users/#{#user[0].id}"
else
flash[:errors] = #user[0].errors.full_messages
redirect_to "/users/#{#user[0].id}/edit"
end
end

I am getting this error message after submitting a test post: param is missing or the value is empty: content?

I am trying to submit a test post through my form, and I am getting this error: param is missing or the value is empty: content. I am requiring "content" and permitting a "title". Both fields were filled out when submitting the post or "thought" in my app. I believe the problem has something to do with strong parameters. I can't find the answer anywhere else on the internet. Here is my controller.
class ThoughtsController < ApplicationController
def index
end
def new
#thought = Thought.new(params[:id])
end
def create
#thought = Thought.new(params[post_params])
#thought.save
if #thought.save
redirect_to #thought
else
render :new
end
end
private
def post_params
params.require(:content).permit(:title)
end
end
Thanks for the help.
The following should work. You propably understand the strong_parameters a bit wrong. If your thought object has :content and :title attributes, they should be listed in permit parenthesis - this will mean you allow their mass-assignment.
def create
#thought = Thought.new(post_params)
if #thought.save
redirect_to #post
else
render :new
end
end
private
def post_params
params.require(:thought).permit(:content, :title)
end

Wrong number of arguments error(1 for 0) in Posts controller, rails 4?

I am getting the error message "wrong number of arguments error(1 for 0) in my posts controller in my show action. I will comment the end of that specific line. Thanks for the help.
def show
#post = Post.all(:order => 'created_at DESC') #this is the error line
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to #post
else
render :new
end
end
You'll want to read the the latest Rails Active Record Query Interface Guide. A lot has changed lately. The short answer is that you now chain together conditions. And .all does not take any arguments -- as the error message is telling you. Instead, you want to use the .order() method:
#posts = Post.order(created_at: :desc)
You either have to show 1 post, and it will be:
#post = Post.find(params[:id]) # show
or all posts
#posts = Post.order('created_at DESC') # index
Taking into account the fact, you write this in show action, you probably meant first.
Also small recommendation regarding strong parameters.
Instead of writing this #post = Post.new(params[:post]) you would rather want to write in #create:
#post = Post.new(post_params)
private
def post_params
params.require(:post).permit(:title, :body) #whatsoever your post has
end

Ruby - can't get JSON params into my controller

Hi and thanks for taking the time to answer my question!
I have the following code in my api/ProjectController:
class Api::ProjectsController < ApplicationController
respond_to :json
def index
respond_with Project.all
end
def show
respond_with Project.find(params[:id])
end
def create
#project = Project.new(project_params)
if #project.save
redirect_to #project
else
render 'new'
end
end
end
I keep getting the following error:
undefined local variable or method `project_params' for #<Api::ProjectsController:0x00003d6d80b448>
When I change the second line in the create method to:
#project = Project.new(params[:project])
I get the following error:
ActiveModel::ForbiddenAttributesError
I am using ember and am sending JSON representation of the Project object from the front end. In both instances this is the json that's being propagated to the controller:
{"project"=>{"name"=>"asdfsdfsdf"}}
Can someone please spot where the mistake is.. I feel like I'm spending more time on this than I really should.. :/
Thank you so much and happy new year!!
You must define the project_params method that you're trying to use:
def project_params
params.require(:project).permit(:name)
end
You'll find more information and example on Rails 4 Strong parameters.
Looks like you don't have the project_params method defined in your Api::ProjectsController class. You need to add a method to your Api::ProjectsController called project_params like:
def project_params
params.require(:project).permit(:attribute)
end
Just replace the :attribute symbol with the actual attributes for the corresponding fields in your form. So if you have a 'name' and 'start_date' field for your project, then your require will look like params.require(:project).permit(:name, :start_date).

Rails custom validation without raising exception

I have a rails model with a start_time timestamp, which should obviously be in the future, which is what my validation should ensure.
appointment.rb
validate :start_time_in_future, :on => :create
private
def start_time_in_future
errors.add(:base, 'Start time must be in the future') unless self.start_time > Time.now
end
appointments_controller.rb
around_filter :start_time_in_future
def create
#appointment = Appointment.create(foo_params)
redirect_to #appointment
end
private
def start_time_in_future
begin
yield
rescue ActiveRecord::RecordInvalid => e
redirect_to request.referrer, :alert => e.message
end
end
And it all works just fine, but its so over the top. Can't I just have a custom validation that fails with a message instead of an exception?
I think you can do that by changing your create method like this
def create
#appointment = Appointment.new(foo_params)
if #appointment.save
redirect_to #appointment
else
render "new"
end
end
In your new template, just show error messages by retrieving it from #appointment object like this
#appointment.errors.full_messages
This is my fault and I feel like an idiot.
I made a class method called .confirm! that uses .save! with a bang.
If you want exceptions, use bang methods, if you don't, use .save and .create()

Resources