How to create method that converts attribute's value to new value - ruby-on-rails

I have a form in which users input a number for the attribute :bytesize, which has an integer datatype. The number represents the amount of bytes for my object #catcher.
I'd like to have a method that will convert the value of :bytesize to megabytes. That is, I'd like to be able to run #catcher.mbsize, and that will display the number of megabytes for that object.
I'm pretty new to Rails, so my apologies if this seems obvious.

Conversion methods are pretty straight-forward:
class Catcher
def mbsize
self.bytesize / (1 << 20)
end
end
Remember that attributes are internally stored as instance variables, so attr_accessor :bytesize is stored in #bytesize.

You need to add mbsize column to your db.
In controller:
def create
#other code
def mbsize
#bytesize / (1 << 20)
end
#catcher.mbsize=mbsize
#cather.save
end
EDIT:
If you don't need related DB record, you can simply define this method in Catcher model:
def mbsize
bytesize=self.bytesize
mbsize=#your method of converting
end
By some reason your bytesize is sting. You can convert it into integer by .to_i method

Related

How can i refactor this Ruby, Rails code?

I'm new at Rails... Is there a better way to refactor this code:
def get_product_price_minimum
Product.minimum(:price).to_i
end
def get_product_price_maximum
Product.maximum(:price).to_i
end
You can define something like "prices" (a vague method name, to avoid using get_ or set_ prefixes) to expect an argument, which would be the maximum or minimum for which to query your model:
def prices(what)
Product.public_send(what, :price).to_i
end
Then you can use it by passing the minimum or maximum as a symbol or a string.
I'm not sure your function works
but you can try (if price is column and price is a int not a string)
def get_product_price_minimum
Product.order('price').last
end

looping over columns in a model using Ruby

I'm trying to loop through all the columns of a model and (1) set the value to lowercase and (2) trim it but I can't seem to get the syntax right. This is what i have so far:
#response.attributes.each do |attr_name, attr_value|
#response."#{attr_name}".downcase.strip!
end
I've searched around and can't seem to find an example of actually setting the value of the model column. All the examples I find deal with displaying the value or field name of each column. In other languages there is an evaluate or eval function to do this but I can't seem to find the equivalent in Ruby.
You can use the write_attribute method to alter an ActiveRecord attribute by name
#response.attributes.each do |attr_name, attr_value|
#response.write_attribute( attr_name, attr_value.downcase.strip )
end
Outside of ActiveRecord framework it is common to use the send method to call a bunch of accessors by name. That would work here, too:
#response.attributes.each do |attr_name, attr_value|
setter = "#{attr_name}="
#response.send( setter, attr_value.downcase.strip )
end
However, the authors of ActiveRecord have foreseen this need, and the write_attribute syntax would be my recommendation here.
You should try this code:
#response.attributes.each do |attr_name, attr_value|
#response[attr_name.to_sym] = attr_value.to_s.downcase.strip
end
Then check #response. It will assign all the values with downcase and stripped in #response variable.

Convert Class Object to string in Ruby

I m in a situation where i need to convert an Object to string so that i can check for Invalid characters/HTML in any filed of that object.
Here is my function for spam check
def seems_spam?(str)
flag = str.match(/<.*>/m) || str.match(/http/) || str.match(/href=/)
Rails.logger.info "** was spam #{flag}"
flag
end
This method use a string and look for wrong data but i don't know how to convert an object to string and pass to this method. I tried this
#request = Request
spam = seems_spam?(#request.to_s)
Please guide
Thanks
You could try #request.inspect
That will show fields that are publicly accessible
Edit: So are you trying to validate each field on the object?
If so, you could get a hash of field and value pairs and pass each one to your method.
#request.instance_values.each do |field, val|
if seems_spam? val
# handle spam
end
If you're asking about implementing a to_s method, Eugene has answered it.
You need to create "to_s" method inside your Object class, where you will cycle through all fields of the object and collecting them into one string.
It will look something like this:
def to_s
attributes.each_with_object("") do |attribute, result|
result << "#{attribute[1].to_s} "
end
end
attribute variable is an array with name of the field and value of the field - [id, 1]
Calling #object.to_s will result with a string like "100 555-2342 machete " which you can check for spam.

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

Rails, using time_select on a non active record model

I am trying to use a time_select to input a time into a model that will then perform some calculations.
the time_select helper prepares the params that is return so that it can be used in a multi-parameter assignment to an Active Record object.
Something like the following
Parameters: {"commit"=>"Calculate", "authenticity_token"=>"eQ/wixLHfrboPd/Ol5IkhQ4lENpt9vc4j0PcIw0Iy/M=", "calculator"=>{"time(2i)"=>"6", "time(3i)"=>"10", "time(4i)"=>"17", "time(5i)"=>"15", "time(1i)"=>"2009"}}
My question is, what is the best way to use this format in a non-active record model. Also on a side note. What is the meaning of the (5i), (4i) etc.? (Other than the obvious reason to distinguish the different time values, basically why it was named this way)
Thank you
You can create a method in the non active record model as follows
# This will return a Time object from provided hash
def parse_calculator_time(hash)
Time.parse("#{hash['time1i']}-#{hash['time2i']}-#{hash['time3i']} #{hash['time4i']}:#{hash['time5i']}")
end
You can then call the method from the controller action as follows
time_object = YourModel.parse_calculator_time(params[:calculator])
It may not be the best solution, but it is simple to use.
Cheers :)
The letter after the number stands for the type to which you wish it to be cast. In this case, integer. It could also be f for float or s for string.
I just did this myself and the easiest way that I could find was to basically copy/paste the Rails code into my base module (or abstract object).
I copied the following functions verbatim from ActiveRecord::Base
assign_multiparameter_attributes(pairs)
extract_callstack_for_multiparameter_attributes(pairs)
type_cast_attribute_value(multiparameter_name, value)
find_parameter_position(multiparameter_name)
I also have the following methods which call/use them:
def setup_parameters(params = {})
new_params = {}
multi_parameter_attributes = []
params.each do |k,v|
if k.to_s.include?("(")
multi_parameter_attributes << [ k.to_s, v ]
else
new_params[k.to_s] = v
end
end
new_params.merge(assign_multiparameter_attributes(multi_parameter_attributes))
end
# Very simplified version of the ActiveRecord::Base method that handles only dates/times
def execute_callstack_for_multiparameter_attributes(callstack)
attributes = {}
callstack.each do |name, values|
if values.empty?
send(name + '=', nil)
else
value = case values.size
when 2 then t = Time.new; Time.local(t.year, t.month, t.day, values[0], values[min], 0, 0)
when 5 then t = Time.time_with_datetime_fallback(:local, *values)
when 3 then Date.new(*values)
else nil
end
attributes[name.to_s] = value
end
end
attributes
end
If you find a better solution, please let me know :-)

Resources