Rails: How to use the find method on an arbitrary index - ruby-on-rails

I have created a model that has a string as a unique identifier.
I created a migration to add an index on that string and set it to be unique.
How can i access a database entry by just passing its unique identifier string to the find method, for example
#object = Object.find(params[:unique_id])
At the moment, all i get is an ActiveRecord::RecordNotFound exception...
Couldn't find Object with id=abc
...when i try to access Object.find('abc')
The where method is no alternative as this gives me back a relation.

Object.find(:unique_id) searches on the column 'object_id'; If you want to search on an other column, use Object.find_by_[column_name]!(:unique_id). This will raise an exception if the record can't be found, as would do the find method.

Related

Undefined method for NilClass in rails console

I've a model named "ListingInfo", whenever I try to generate new object from this model, it shows the "undefined method for nilclass". I'm unable to add its attributes other than id.
I've also tried "create" method but on running "ListingInfo.count.all", it still returns zero(please see second image for more clarity). Means, it is still not being saved to database.
You need to create the object. Using ListingInfo.new will only instantiate it but won't validate it or save it to the DB. Also you shouldn't pass a value on the id that's generated automatically from Rails.
Solutions:
Use new and then save the object
listing = ListingInfo.new
listing.save
Use create
ListingInfo.create
ActiveRecord::Base documentation
create(attributes = nil) {|object| ...}
Creates 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.
new(attributes = nil) {|self if block_given?| ...}
New objects can be instantiated as either empty (pass no construction
parameter) or pre-set with attributes but not yet saved (pass a hash
with key names matching the associated table column names). In both
instances, valid attribute keys are determined by the column names of
the associated table — hence you can‘t have attributes that aren‘t
part of the table columns.

Updating if exist or create if not rails

So im using an api to get info on weather, its executes everyday, what im trying to do is to get updated if already exist, and create a new one if it doesn't in table.
I do want to update all attributs when udpdating.
i did try
model = Model.where(column_name: value).first_or_initialize(locked: false)
but i get an error saying :
unknown attribute locked for Model
raise UnknownAttributeError.new(self ,k.to_s)
If you need anything, ask and i will comment or edit. Im newb to ruby and rails
Firstly, the model.Model part should be just Model, as Model is your class.
locked is supposed to be a column/attribute of the Model class, although it seems is not the case judging from your error. Therefore, I'm gonna use other_column_name as an example.
Explanation of what this is doing:
Model.where(column_name: value).first_or_initialize(other_column_name: some_value)
Model.where(column_name: value): gets models that satisfy the condition column_name == value
first_or_initialize: if a model such that column_name == value was found, that one is returned. Otherwise, it initializes a model with column_name = value.
By passing other_column_name: some_value, if the model was not found and needs to be initialized, it sets other_column_name to some_value but: 1) it does not update it if it was initially found and 2) it does not save the record.
The equivalent of first_or_initialize that saves the new record would be first_or_create but this would still not update the record if it already existed.
So, you should do something like this:
m = Model.where(column_name: value).first_or_initialize
m.other_column_name = some_value
m.save
This way, you first get a model where column_name is value or initialize a new one with this value if it didn't already exist. Then, you set the attribute other_column_name to some_value and save the model.
A one-liner alternative would be
Model.where(column_name: value).first_or_create.update(other_column_name: some_value)
However, note that if it needs to be created, this one will perform 2 queries (the insert and the update).
About the error part. It says the attribute locked does not exist on the Model record. Are these classes you created? Are you using some pre-existing project? You could try posting Model.attribute_names and maybe your schema.rb
Firstly refer to the docs here
A table by the name of weather with the following attributes location: string temperature:integer wind:string needing to be updated or initialized based on the location would work like this
#weather_record = Weather.find_or_initialize_by(location: location_value)
#weather.temperature = -60
#weather.wind = strong
#weather.save
Next, never, ever use a reserved name for a model so do not have Model as the name of your table
Lastly in your example
model.Model.where(column_name: value).first_or_initialize(locked: false)
you are saying
a_record.ClassName.where which is just wrong, If you are using a class method then start with the class name e.g. Weather.where if you are using instance methods then use the instance name e.g. an_instance_of_weather.some_field
Try this mate:
column_name_value = (Way that you get the info from data)
model = Model.find_or_initialize_by column_name: column_name_value
Let me know if worked!

How to get active record's name after using find .where

Straight forward here:
<% #yyy = CityRace.where(city_race_id2: "3") %>
<% #xxx = #yyy.name %>
The #yyy is returning the proper record using the ID I have passed into it, but I'm trying to get the objects name. For some reason .name isn't working. Any idea what I'm going wrong here?
How do I find a record's name where id = a certain id?
where returns an ActiveRecord_Relationship, meaning an object containing CityRace objects for every row in the database with city_race_id2 equals to 3, no matter if there's only one, the result is an ActiveRecord_Relationship object, and that doesn't respond to name.
If you need the name of a particular object from that result, you can access to the specific element by its index and invoke name on it, e.g:
CityRace.where(city_race_id2: "3").first.name
Or to retrieve the name from every object:
CityRace.where(city_race_id2: "3").pluck(:name)
this one returns an array of strings, so, you must iterate over them to print them all or get a specific one.
In the other hand if you need a single row from the query, use find_by:
CityRace.find_by(city_race_id2: "3").name
.where returns an ActiveRecord::Relation which behaves like an array. You can think of it like a special kind of array that allows you to chain on more active record queries on it. When you call certain methods like each or to_a it evaluates the query into an actual array.
In any case, what you are looking for here is not something array-like. You want #yyy to refer to a single record.
Simple fix, just use find_by instead of where. Also take a look at https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find and find vs find_by vs where

Active record where query for value inside of an array

Question: Is it possible to build a class method scope that can query objects based on values inside an array in a table? If yes, how can I do this?
In my example, I have a “wells” table that has an array field called “well_tags”. I want to build a query that returns all objects that have a specified value (such as “ceramic”) in the wells_tags array. The basic query would be something like this:
#well = Well.all
#query = #well.where(“well_tags contains ceramic”)
And then the class method scope would look something like this, with the “well_tag_search” param passed in from the controller:
class Well < ActiveRecord::Base
def self.well_tag_filter(well_tag_search)
if well_tag_search.present?
where(“well_tags contains ceramic")
else
Well.all
end
end
I found another post that asks a similar question (see link below), but I cannot get the answer to work for me...the result is always 'nil' when I know there should be at least 1 object. I am a beginner using sqlite (for now) as my database and rails 4.0.
Active Record Query where value in array field
Thanks!
UPDATE: some progress
I figured out how to create an array of all the objects I want using the ‘select’ method. But I still need to return the results as an Active Record object so I create a class method scope.
#well = Well.select
{ |well| if well.well_tags.present?
then well.well_tags.include? ‘ceramic' end }
#well.class #=> array
Not sure where Show is coming from.
Can you try doing Well.all instead of Show.all?

rails 3, how can a reference to fieldname pull data from another source if field is empty?

In my app, users have one "template" record (in Template table) that sets defaults for their data.
Then they create multiple records in (Userdata table).
For each Userdata record, if they enter data into a field, the app uses THAT data (of course). But if Userdata.foo is empty I'd like to use Template.foo instead, transparently. And if both are empty, then it's "empty".
I'm pretty sure the right answer is NOT to code every single place I use every field:
if Userdata.foo.blank?
Template.foo
endif
And I assume it's a matter of somehow defining my model to redefine the fieldname somehow?
And I'm hoping there's some way to not even have to code the model method field-by-field, to basically say "if the field in UserDayta is blank, use the one in Template instead..."
You can define a method in your User model like so:
def fetch_attribute(att)
if self.userdata[att].nil? and self.template[att].nil?
return nil
elsif self.userdata[att].nil?
return self.template[att]
else
return self.userdata[att]
end
end

Resources