get current variable Rails, in before_save - ruby-on-rails

Is there a way to get the current variable?
lets say that i have a "title" attribute in a method and i want to check in with the old value of the variable ?
how could i accomplish this ?

ActiveRecord provides a whole set of methods which work on "Dirty" attributes.
In your case, you can call title_was to get the most recently saved version of that variable

If you want to know all the changed attribute and their old values you can use changed_attributes method which will return hash that contains all the changed attribute with their previous values (note that the hash content can be retrieve before saving the new object).
Let assume that you have an object with old_name title:
a = YourModel.where(:title => "old_name")
a.title = "new_title"
a.changed_attributes
Results will be":
{"title"=>"old_name"}
But after saving your changes:
a.save
a.changed_attributes
The results will be empty hash:
{}

Related

Rails: Use custom class for activerecord attribute (update in place)

If I have a jsonb column activerecord returns the attribute as a hash but somehow retains a reference to that object so it is able to detect changes. That is, code behaves like the following
pub = Publication.find("554a1791-e690-4a45-8207-db6b66fa3480")
md = pub.metadata #jsonb column
pub.metadata_changed? #false
md['foo'] = 'bar'
pub.metadata_changed? #true
I'd like to replace the hash class with an instance of a custom class but retain the modification in place behavior. What do I need to do to achieve this? Do I overload some kind of method to check if the object is dirty?

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!

Calling .attributes on model object avoid fileds with nil values

When attributes() is called on a Mongoid model object it excludes the fields with nil values, is there a way to get all the fields irrespective of their values?
media = Media.first
media.attributes #=> ignores nil values
Also, FYI this happens when a record is created with only a few attributes, but when we create a record by assigning nil values to the remaining fields explicitly it works fine!
Any help would be highly appreciated!
mongoid used to remove empty fields. If you kept some fields empty on insert, mongoid will removes them.
Use media.to_json instead for your case.

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?

How do I prepopulate from a previous object in rails?

I have this line of code
Account.build_address
and this works but I need to prepopulate is with a previous address so if i had the params i could do
Account.build_address(params[:address])
But i dont have the params I have a previous address object so for the sake of example i can say
#previous_address = Address.first
Account.build_address(#previous_address)
But I dont think this is in the format i need to prepopulate...any ideas
You don't need to build, you can just clone the existing object:
#previous_address.clone
That will copy all columns of the #previous_address model, except for the id field
Try this:
#previous_address = Address.first
Address.build_address(#address.attributes)
#address.attributes returns a hash of the object's ActiveRecord attributes... so as long as build_address expects a hash, it should generate an object equivalent to the address you pass in.

Resources