Finding a record which I had created

I thought this is an easy one, but: I have created a record, and later
would like to retrieve it again.

Here is an excerpt of my schema:

create_table “dicts”, force: true do |t|
t.string “dictname”

end

My model ensures that dictname is unique:

validates :dictname,
presence: true,
length: { minimum: 3 },
format: { with: /\A\D/ },
uniqueness: true

In my controller, I tried this to fetch a Dict object, when the value
for the :dictname field is stored in variable dict_name:

if Dict.exists?(:dictname => dict_name)
logger.debug('found dictionary with name '+dict_name)
dictid=Dict.where(:dictname => dict_name).select(‘id’).first.id
logger.debug(‘dictid=’+dictid.inspect)
@dict=Dict.find(dictid)

However, the line to calculate dictid fails with

TypeError (can’t cast Hash to integer)

which would suggest that the hash argument to the ‘where’ method is
unexpected. But this can’t really be, can it?

So, my questions:

  • Why do I get this error?

  • How do I fix it?

  • The whole procedure to get at my Dict record, looks unnecessarily
    convoluted to me. Isn’t there an easier way to do it?

On May 26, 2014, at 8:38 AM, Ronald F. wrote:

My model ensures that dictname is unique:
if Dict.exists?(:dictname => dict_name)
unexpected. But this can’t really be, can it?

So, my questions:

  • Why do I get this error?

  • How do I fix it?

  • The whole procedure to get at my Dict record, looks unnecessarily
    convoluted to me. Isn’t there an easier way to do it?

ActiveRecord already has a finder that can do all this in one line:

Dict.first_or_create(url: params[:dictname])

Assuming that’s the only thing needed to create or find an existing
Dict, you should be all good there.

Walter

Sorry, meant dictname:, not url: that’s my app that has URLs, not yours.

Walter

Walter D. wrote in post #1147113:

ActiveRecord already has a finder that can do all this in one line:
Assuming that’s the only thing needed to create or find an existing
Dict, you should be all good there.

No, it should not create one. If there is no suitable record, I want to
display an error message to the user. Hence, find_or_create isn’t
suitable for me.

BTW, I also tried

Dict.find(:dictname => dict_name)

but this too complained that there is a hash, which can’t be converted
to an integer.

Ronald

On May 26, 2014, at 9:03 AM, Ronald F. wrote:

Dict.find(:dictname => dict_name)

but this too complained that there is a hash, which can’t be converted
to an integer.

Dict.find_by_dictname() will do that for you. If you add the bang to it,
you will get a full-on error, if you don’t you will get nil and no error
is raised. If you are using the error to trigger your 404, then you want
the bang version.

Walter

Thanks, I will try this!

I wonder: Where do I find a specification for this feature? I guess
Rails automatically generates this kind of find_by_… functions for
each attribute in my model, which as “uniqueness” set. Where is this
documented? My biggest problem with rails is getting from the API docs
the information I need.

Just for my understanding: Could you also please explain, why my
original (complicated) version failed?

Ronald

This could be written as this:

@dict = Dict.where(:dictname => dict_name).first

It will either return a record, or nil.

Walter

Walter D. wrote in post #1147134:

@dict = Dict.where(:dictname => dict_name).first

It will either return a record, or nil.

Thanks a lot. This works perfectly well!

Ronald