How do I prepopulate from a previous object in rails? - ruby-on-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.

Related

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!

For each in by reference or value

I have the following code:
dim key
for each key in Request.Querystring
'do something
key = sanitized_param(key)
next
My question for you classic-asp connoisseur, does classic-asp, or asp in general, pass the variables as references(memory), or by value? Trying to figure out if I sanitize the key variable and pass it back to itself, is it just "alive" for that loop, or does the new value get passed to the original QueryString?
Request.QueryString retrieves the query string parameters by value from the page headers.
You can only make changes to a query string once its been retrieved via Request.QueryString, but you can't make changes directly to Request.QueryString as it's read-only (If you could make changes you would presumably use Response.QueryString, but this isn't a valid response command).
I'm guessing you're trying to sanitize all your query strings in one go? This isn't really possible or indeed necessary. You would typically sanitize a query string as and when you request it:
Response.Write(sanitized_param(Request.QueryString("myQS")))
Or to assign the query string to a variable first then sanitize it:
Dim myQS
myQS = Request.QueryString("myQS")
myQS = sanitized_param(myQS)
' or
myQS = sanitized_param(Request.QueryString("myQS"))
Once the query string has been assigned to a variable and sanitized you're able to reference that variable as often as you like without having to pass it to your sanitize function again.
Also, your example code doesn't make much sense. The key value in your for each loop is referencing just the names of your query strings and not their values. If Response.QueryString was a valid ASP command you would do:
Response.QueryString(key) = sanitized_param(Request.QueryString(key))
But again, this isn't possible.
EDIT: This solution might be what you're looking for:
Create a dictionary object, call it "QueryString" for example. Loop through all your query strings and add a sanitized version to the dictionary object.
Dim QueryString : Set QueryString = Server.CreateObject("Scripting.Dictionary")
For Each Item In Request.QueryString
QueryString.Add Item,sanitized_param(Request.QueryString(Item))
next
Now, to retrieve a sanitized version of a query string just use:
QueryString.Item("query_string_name")
Or for the original unsanitized version you could still use:
Request.QueryString("query_string_name")
Just like Request.QueryString, the dictionary object is forgiving and won't return an error if you ask for a query string that doesn't exist.
You could also create a function for retrieving sanitized query strings, for example:
Function SanitizedQS(ByVal qsName)
SanitizedQS = sanitized_param(Request.QueryString(qsName))
End Function
And rather than using Request.QueryString("query_string_name") just use SanitizedQS("query_string_name").

Is it possible to update an entire record using an object in rails?

I was wondering if I could update a record (entire row) given a replacement activerecord object.
Something like
Car.find_by(number: 1) = replacement_information_for_car_1
where replacement_information_for_car_1 is a Car activerecord object that I would like to use to replace the old record currently on the table.
You could do something like:
attributes = replacement_information_for_car_1.attributes
attributes.delete('id') # and anything else you don't want/can't be copied
Car.find_by(number: 1).update(attributes)
Not the cutest thing in the world, but it should do the trick.
The thing about ActiveRecord objects is that they have a unique identifier that you don't want to override. You'll have to assign the attributes without the id, that is most likely to be nil in your example.
Car.find_by(number: 1).update(replacement_information_for_car_1.attributes.except(:id))
That's a long line that can be refactored to something like
new_attributes = replacement_information_for_car_1.attributes.except(:id)
Car.find_by(number: 1).update(new_attributes)

How to update table row from values determined within controller

ruby_on_rails rails 4 assignment non-screen data to insert record
Rather than using screen values (e.g. simple_form_for #user_evaluation_result) to populate the columns to insert a row I need to calculate some of the values in controller.
For example if I have these statements in the controller
….
# which if I had simple_form_for user_evaluation_result would get populated by the screen
#user_evaluation_result = UserEvaluationResult.new(user_evaluation_result_params)
….
# standard stuff I use for screen derived updates
def user_evaluation_result_params
params.require(:user_evaluation_result).
permit(:evaluation_assumption_id,
:company_listing_id,
:target_share_price_dollars )
end
How do I assign values to :user_assumption_id etc so that insert works. I have tried all sorts of statements. Alternatively do I use another format instead of calling "def user_evaluation_result_params".
Thanks in advance - Pierre
I'm hoping I've interpreted the question properly...
First, to make sure we're on the same page... The code inside of your user_evaluation_result_params method is using Strong Parameters to create an ActionController::Parameters object for the purpose of protecting your model from unpermitted mass-assignments. So, in general, when you're creating or updating an ActiveRecord object from a form in a view template, you want to use Strong Parameters so that users can't manipulate your form to set attributes that you're not expecting.
That said, if you want to set attributes on an object you don't have to use mass assignment. Here is an example of using one-at-a-time assignment (the opposite of mass-assignment):
obj = MyObject.new
obj.attr_one = "One"
obj.attr_two = "Two"
obj.save
There is nothing wrong with this approach other than that it's kind of a lot of work for the general case. So mass-assignment just saves us from having to do this all the time. But it sounds like this one-at-a-time assignment is what you're wanting in this case. So try something like this:
def create
#user_evaluation_result = UserEvaluationResult.new
# assuming you have a UserAssumption object instance in `my_user_assumption`
#user_evaluation_result.user_assumption = my_user_assumption
#user_evaluation_result.some_other_attr = "some value"
#user_evaluation_result.save
end
Note, instead of setting #user_evaluation_result.user_assumption_id directly, as you asked about, it is preferred to set the actual object association as I did above. Try to keep associations outside of mass-assignment and use object relationships to build up your object graphs.
Or, if you have some attributes coming from a form you can mix and match the two approaches:
def create
#user_evaluation_result = UserEvaluationResult.new(user_evaluation_result_params)
# assuming you have a UserAssumption object instance in `my_user_assumption`
#user_evaluation_result.user_assumption = my_user_assumption
#user_evaluation_result.some_other_attr = params[:user_evaluation_result][:some_other_attr]
#user_evaluation_result.save
end
private
def user_evaluation_result_params
params.require(:user_evaluation_result)
.permit(:evaluation_assumption_id,
:company_listing_id,
:target_share_price_dollars)
end

get current variable Rails, in before_save

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:
{}

Resources