Overriding data of local copy of database object, Rails - ruby-on-rails

I want to be able to override the instance of a database object without affecting the original
Object #users = User.all with a table attribute :status
#users[0].status = nil
Causes the status attribute to equal to nil when I read it with #users[0].status
However, when I do:
#users.find(1).status = nil
Does not change the status, notably a sql query is called when I use the find command, as such it is the database data that I am receiving
I tried using the .dup and .clone methods
#users=User.all.dup
Did not work
How do I go about with this? Do I have to create a temporary table? I am using postgres

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 mark as outdated an ActiveRecord object attribute?

I have a database trigger that modifies a field on INSERT. Then when I run object.my_attribute it returns nil instead of lets say 42.
If I do object.reload.my_attribute, this is fine. But I don't want to reload the whole object or part of it unless it is necessary. And I believe code shouldn't be concerned when and how an object was created. It should just be correct.
Is it possible to mark that particular attribute as outdated and any attempt to get its value to result in a query that fetches it from database?
For example:
after_save :forget_my_attribute
def forget_my_attribute
forget_field :my_attribute
end
I think it's better to make some service object where field is modified and call it when create the record. CreateModel.call(args) instead of Model.create(args). It will be more clear than database trigger I think
But you can do something like this
after_create_commit :fetch_my_attribute
def fetch_my_attribute
self[:my_attribute] = self.class.find_by(id: id)[:my_attribute]
end
Or more flexible fetch attribute you need dynamically
def fetch_attribute(atr)
self[atr] = self.class.find_by(id: id)[atr]
end
object.fetch_attribute(:my_attribute)

Rails + MongoDB not returning all documents in collection

I need all the documents in one of my collections to create association in between my parent model to child. The problem is I only have the string of my ObjectId. So I am finding the object by string and then set via parent.child = foundObject. So, to achieve this I created a private method as below, to not to create DB request each time I need that child object.
def childs
#childs ||= Child.all
end
But this is not working as expected. When I run ModelName.all it returns below result; not all the docs in collection.
=>
#<Mongoid::Criteria
selector: {}
options: {}
class: ModelName
embedded: false>
And this causes my loop to create another DB request each time I try to associate child to parent. I prevent this by using below method.
def childs
#childs ||= Child.all.select { |v| v.id.present? }
end
I believe there should be a way of collecting all documents in MongoDB, I know the idea of Mongoid::Criteria and what it actually does. But in some case, I need all the objects to be stored in one variable. Do not want to create unwanted DB queries each time I need one specific document in a model.
I could not find a way to solve this specific problem and I think it's kind of impossible since MongoDB is not a relational DB It's quite hard to collect information at the same time with querying. What I used is "MongoDB views" and this solved a lot. Here is the docs. There you can read and find yourself an approach to figure out your own problem.

Grails - Retrieving fresh instance from database

Can you force the DomainClass.get(id) functionality in Grails to pull a fresh instance from the database rather then using the local copy retrieved previously in the session?
I would like to compare if a property of the instance has changed:
Example:
def myInstance = MyClass.get(params.id)
myInstance.properties = params.data // updates the instance, but does not save it
// stuff happens
def myDbInstance = MyClass.get(params.id) // would like this to pull a fresh copy from the database, unchanged to allow for comparison
if(myDbInstance.value != myInstance.value) {
// do something if has changed
}
Thank you.
Use can use the refresh() method to force an instance to reload from the database.
In case we want to compare the fields updated in view to the ones that are already available in the database, refresh() would update the instance that is yet to be saved in the database.
In that case getPersistentValue('field_name') on the instance would fetch the value in database and can be used for comparisons.
If there is employeeAllocationInstance already available in controller's update action for e.g.,
and we want to compare the updated fields lets say jan allocation
then
existing_allocation = EmployeeAllocation.get(employeeAllocationInstance.id)
would have updated the values in employeeAllocationInstance so we can do
existing_allocation?.getPersistentValue('jan')?.value to get the value that is stored in database (which is yet to be updated)

Resources