Finding a particular attribute's value from a model in Rails - ruby-on-rails

I'm trying to find the value of a particular model's attribute in rails. Here's what my code in the User controller's 'create' method looks like:
#user = User.find(1, :select => :money)
existing_money = #user
puts "#{existing_money}"
In my Heroku logs I'll see a variant of the following output instead of the :money integer for that particular user (with :id 1)
#<User:0x00000004e7cbc0>
Any thoughts? Thanks!

#user = User.find(1, :select => :money)
You are setting the #user instance variable with an object that has only one value, namely the money value. For now, all this does is save you a few bytes, by leaving off things like id, email, and any other columns you have in that table. It does however still return an object with attributes, the only difference is your object has only one attribute to call.
existing_money = #user
Given that #user is still an object with a single attribute, you now save this object in the existing_money local variable. What you probably want to do is *only store the money attribute in this variable`.
So you'd need this:
existing_money = #user.money
puts "#{existing_money}"
After the above change, this puts statement should return the attribute value, not the object encapsulating the attribute.

As existing_money is just the object you are seeing the object's ID.
As you want the money attribute you have to reference that too.
puts "#{existing_money.money}"

Related

rails use form input value before save

I have a form in rails with input values, and 1 of the values is a LOV (List of Values) and a second input field is also a LOV but depends on the input of the other field.
The input value of the first field is not saved in between. So I need to use that field value before it is saved.
So, the example:
I choose a company from the list of values of all companies for the field supplier, the second field supplier_address will be a LOV with all the addresses of that company, so the LOV of the second field is dependent on the value chosen in the first field, company.
What I tried:
def new
#purchase_requisition = PurchaseRequisition.new
#purchase_requisition.number = find_next_user_value("Purchase_Requisition")
##purchase_requisition.supplier_address_id = PurchaseRequisition.new.purchase_requisition_params[:supplier_id]
#purchase_requisition = PurchaseRequisition.new(purchase_requisition_params)
respond_to do |format|
#purchase_requisition.supplier_address_id = PurchaseRequisition.new.purchase_requisition_params[:supplier_id]
end
end
but I still get the error:
param is missing or the value is empty: purchase_requisition
Can someone please help me?
Thank you!!!
The error you're encountering isn't being caused by the code you've provided. You're probably using strong parameters and have a method like this:
def purchase_requisition_params
params.require(:purchase_requisition).permit(# some list of attributes #)
end
The problem is that params[:purchase_requisition] doesn't exist. Probably because the form_for in your view isn't referencing a purchase_requisition object. Try adding as: to your form_for to send your params under that param key:
form_for #requisition, as: :purchase_requisition, ....
Otherwise, you'll have to post more details about your view and controller to help isolate the issue you're having.
Also, in your controller code you want:
PurchaseRequisition.new(purchase_requisition_params[:supplier_id])
Instead of:
PurchaseRequisition.new.purchase_requisition_params[:supplier_id]
Supposing, all of your parameters belong to the same object (there isn't any nested attribute), this can be what you are looking for:
def purchase_requisition_params
params.require(:purchase_requisition).permit(:org_id, :document_type, :number, :supplier_id, :supplier_address_id, :partner_id, :project_id, :construction_site_id, :purchase_order_date, :expected_receiving_date, :promised_receiving_date, :supplier_order_number, :supplier_shipping_number, :supplier_invoice_number, :currency, :status) ##you don't need id here
end

RoR Take atrributes from ActiveRecord::Relation

I'm a novice at RoR. Tell me please how to take attributes from ActiveRecord::Relation? For Example I write:
#user = User.where(code: 123)
next I want to take attribute id
id = #user.id
but this method is not working. Thanks in advance
When use .where it gives you an active record relation so you can't find id directly on it because it's a relation not a single model object.
Fix:
You can do
#user = User.where(code: 123).first
OR
You can use dynamic finders
#user = User.find_by_code(123)
If you want to find single user with code == 123, you can use find_by method, like this:
#user = User.find_by(code: 123)
It returns User instance, so you can call id method on it.
EDIT: If you use Rails prior to 4.x version, you can use dynamic find_by_code finder:
#user = User.find_by_code(123)
You are using where clause it returns array. Use it like :
#user = User.where(code: 123).first
Above is not right way for query. So you can also write your code to find user like :
#user = User.find_by_code(123)
With above two ways you get single object and you can find any attribute from it. #user.id etc
I guess you are missing first, where returns an array of objects, so you need to use first to get the object out of array
Do this
#user = User.where(code: 123).first
id = #user.id

Rails serialized hash - is it possible to specify a data type?

I'm serializing form input into a hash. Is it possible to force some of the inputs into integers?
For example, if I do #user.update_attributes(params[:user]), and one of the params is supposed to be a number, that number will get stored a string like "123".
Is it possible to make sure it is stored as an integer?
To be clear:
My User model looks like
class User < ActiveRecord::Base
...
store :preferences, accessors: [:max_capacity]
...
end
and my form might have an input like
<input name="user[preferences][max_capacity]" type="text"/>
This will cause max_capacity to be stored as a String. Can I force it to be an integer when I store it?
You can modify the user object that is stored in the params hash directly before you save it. If you convert max_capacity from a string into an integer you will want to account for the case when a user submits a bad value for max_capacity. This can be handled with a begin/rescue block.
In your Controller action you could do the following:
def update
max_capacity = params[:user][preferences][max_capacity]
begin
# Attempt to convert into an integer
Integer(max_capacity)
rescue
# If max_capacity was incorrectly submitted: 'three', '04', '3fs'.
redirect_to edit_user_path, :alert => "Unable to update user. Invalid max capacity."
else
If it can be converted, do so, and update the user object in the params hash.
params[:user][preferences][max_capacity] = Integer(max_capacity)
end
#user.update_attributes(params[:user])
.
.
.
end

How to get changed values on save

Trying to get previous values from the object on save. Think of this scenario:
#object = {:name => 'Dan', :occupation => 'student'}
#object[:occupation] = 'Full time employee'
#object.value_was[:occupation] # => 'student'
I hope it is understandable enough that there is no method value_was. More over I would like to do the same on model objects:
#student = Student.find(1)
#student.occupation = 'Full time employee'
#student.save
#student.value_was(:occupation) # => 'student'
Any help will be appreciated.
That would be really helpful
ActiveModel includes support for "dirty field marking", which preserves before and after states for changed fields.
You can use #student.occupation_was to get the previous value of occupation, and #student.occupation_changed? to get whether the value has changed or not.
This only works BEFORE the save, as saving resets the changed states of the values. However, you could capture this data in a before_save callback if you need to use it after a record has been saved. You can preserve all of the changes by duplicating #changed_attributes in a before_save, for example, then query on them.

Getting the name of Ruby method for a literal hash query

In a rails application, I have a number of attributes for a model called Record. I want to design a method that when called on an attribute, returns the name of the attribute (which is essentially a method on the Record object). This name is then passed to an Hash, which returns a number (for the sake of this example, say the number is a percentage which is then multiplied by the original attribute value to get a new value).
For example, say my Record has four attributes: teachers, students, principals, and parents. The method would then look like the following:
def name
**something here**
end
and the corresponding new_value method and PRECENTAGE hash would look like this:
def new_value
self * PERCENTAGE[self.name]
end
PERCENTAGE = {
"teachers" => 0.40,
"students" => 0.53,
"principals" => 0.21,
"parents" => 0.87
}
Then, to execute this whole thing, I would do Record.students.new_value, which would return new number of students according to the percentage obtained in the hash.
I know that to get the name of a method that is currently executing, you can do something like this: (found on http://ryat.la/7RDk)
def this_method
__method__
end
but that won't work for me, because I need the name of the previously executed method.
If you have any suggestions as to an alternative approach to accomplishing my goal, I'd be happy to try something else.
Ryan, I'm struggling to understand your question, but I think this is what you want, for record.teachers_percent, for example:
["teachers", "students", "principals", "parents"].each do |attrib|
Record.class_eval <<-RUBY
def #{attrib}_percent
#{attrib} * PERCENTAGE[#{attrib.inspect}]
end
RUBY
end
Although this is probably a cleaner solution, giving record.percent(:teachers) or record.percent("teachers"):
class Record
def percent(attrib)
self.send(attrib) * PERCENTAGE[attrib.to_s]
end
end

Resources