Ruby on Rails Active Record Return Value When Create Fails

Ruby on Rails Active Record return value when create fails?

The answer to your question is, User.create returns a User instance if it succeeds or fails. If it fails because of validations, the instance will be invalid and will have errors:

user.valid? # <= returns false
user.errors.count # <= will be > 0
user.errors.blank? # <= will be false

So your code would change from this:

if user==false or user==nil or user==vals

to this:

if !user.valid?

You can also use this pattern:

user.attributes = vals
if user.save
... save succeeded ...
else
... save failed ...
end

The save method returns a boolean true or false since you are calling it on an existing instance.

But lets get you on the right track in a few other ways:

First: you have this:

if User.exists(vals[:username])

(I'm assuming exits is a method you put on your User model because that's not a Rails thing). Instead of doing that check in your controller, you can just use another validation on the model:

class User < ActiveRecord::Base
...
validates :username, unique: true
...
end

Now when you try to create the user, it will fail validation if you already have one with that name.

Second: You have this:

vals[:create_date] = DateTime.current

This is unnecessary. If you add a column to your model called created_at it will hold the creation date automatically (managed by ActiveRecord). You can add this, and its partner updated_at to your model in your migration like this:

create_table :users do |t|
...
t.timestamps # <= tells rails to add created_at and updated_at
end

Or, since you already have a users table:

add_column :users, :created_at, :datetime
add_column :users, :updated_at, :datetime

Now you will always have the date/time of creation and last update on your user model with no need for additional code.

Third: You have this:

user = User.create(vals, :without_protection => :true)

Don't do this. Instead, change this:

vals = params[:user]

To this:

vals = params.require(:user).permit(:username, :password, :password_confirmation)

And then keep protection on:

user = User.create(vals)

You can add any additional columns you want to bring from your form to the permit() call. This is very important because it is hard to fix this kind of thing later. "If once you go down the dark path, forever will it dominate your destiny."

Fourth: You should not redirect to the user_path if the save failed, because there will be no user model to show. Instead you should re-render your new form. You also don't need flash messages for the errors. If the new form renders, it can check @user.errors and report error messages accordingly. See the ActiveRecord error object documentation.

Finally: You mention that you your validation fails even when your password is properly confirmed. I can't say for sure without seeing your form code, but make sure your password field is called password and the confirmation field is called password_confirmation. Rails looks for this *_confirmation field value specifically when validating for confirmation.

If that doesn't do it, post your form code and I'll revise.

Best way to return recently created object in ActiveRecord?

Just assign the instance you created to a variable:

data = {foo: 'foo', bar: 'bar'}

dummy = Dummy.new(data)
dummy.save!
dummy # the record you just created

Or use create! instead of new and save! like this:

data = {foo: 'foo', bar: 'bar'}

Dummy.create!(data) # returns the created instance or raises an error if not successful

Return true/false on creation of object

You could try

@object = Blah.create()
@object.persisted? # true or false

also if you want to throw an error instead you could use the bang version, be sure to use rescue

@object = Blah.create!()

ActiveRecord not returning all values from a table when I use 'ModelName.all'

@all is an instance of ActiveRecord::Relation. When you are calling:

<%= @all %>

in your view, you are printing that object (and #<BlogPost::ActiveRecord_Relation:0x00007f440816f1e0> is a correct output).

If you would like to display records, then you have to iterate over @all and display them like this:

<% @all.each do |blog_post| %>    
<h1><%= blog_post.title %></h1>
<p><%= blog_post.content %></p>
<% end %>

Update

The latest problem was solved by restarting Rails server

Rails method for only returning a single record and throwing an exception when multiple are returned

I'm not aware of a built in Active Record method that does what you ask but it wouldn't be hard to write your own. Something like:

class YourModel
def self.find_only_one_by_slug(slug)
results = YourModel.where(slug: slug)
if results.size > 1
raise "There should only be one return value."
else
return results.first
end
end
end

I haven't tested the above code so there will most certainly be errors but you get the idea. You could even take this a step farther and add a similar method to active record base that all of your models would have access to.

active record returning all relations of an object that are archived: false

If what you're trying to do is get users without any archived matches the easiest way is by creating a subquery:

class User < ApplicationRecord
def self.potential_matches
pm = PotentialMatch.arel_table
id = arel_table[:id]
where(
PotentialMatch.where(
pm[:mentor_id].eq(id).or(pm[:mentee_id].eq(id))
).where(archived: true).arel.exists.not
).where(active: true)
end
end

This generates the following SQL:

SELECT "users".*
FROM "users"
WHERE NOT ( EXISTS (SELECT "potential_matches".*
FROM "potential_matches"
WHERE ( "potential_matches"."mentor_id" = "users"."id"
OR "potential_matches"."mentor_id" =
"users"."id" )
AND "potential_matches"."archived" = ?) )
AND "users"."active" = ? /* loading for inspect */
LIMIT ?

How to update Rails Controller to return an error when Model.create errors?

The usual rails way is to test the return value of .save:

def create
@feedback = current_user.feedbacks.new(
feedback_type: params[:selectedType],
message: params[:message]
)
if @feedback.save
json_response(@feedback)
else
json_response(@feedback.errors, :some_other_status)
# you could also send @feedback directly and then in your JSON response handler
# to test if the json contains values in the object.errors array
end
end

private

def json_response(object, status = :ok)
render json: object, status: status
end

You can use this doc to find the right statuts code to return https://cloud.google.com/storage/docs/json_api/v1/status-codes



Related Topics



Leave a reply



Submit