Show only a few characters from a string - ruby-on-rails

I have this simple helper (in Rails app):
def shortener(text, text_length = nil)
if text_length.nil?
text_size = 60
else
text_size = text_length
end
#text_size = 60 if text_length.nil? => return the same error as above
if text.length.to_i > text_size.to_i # HERE IS THE ISSUE
return "#{text[0..(text_size-5)]}..."
else
return text
end
end
However, I am getting this error:
undefined method `length' for nil:NilClass
Why am I getting this error? Both parameters exist and are integers.

Because you are using Rails, I recommend you to use Rails built-in helper truncate
truncate("And they found that many people were sleeping better.", length: 25, omission: '... (continued)')
For more information, refer http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-truncate

If for some reason you want to roll your own method instead of using the built-in truncate:
def shortener(text = "", text_length = 60)
"#{text[0...text_length]}..."
end

It means text is nil. Use caller to find out why.

You are getting that error because text is passed as nil.
In order for it to behave like a normal text renderer in rails, you might want to do this:
def shortener(text, text_length = 60)
text ||= ''
if text.length.to_i > text_length.to_i
return "#{text[0..(max_text_length-5)]}..."
else
return text
end
end

Related

Cannot convert data from cookies

I want to make a method that will count the number of user actions on the site.
I have the code:
def actions_counter
if cookies[:"actions"] != nil
cookies[:"actions"].to_i += 1
else
cookies[:"actions"] = 0
end
end
But for some reason this does not work.
NoMethodError in PostsController#show
undefined method `to_i=' for "1":String Did you mean? to_i to_r to_f to_s to_d to_c
Just change your method to
def actions_counter
if cookies[:actions]
cookies[:actions] = cookies[:actions].to_i + 1
else
cookies[:actions] = 0
end
end
The issue is that Ruby understands cookies[:"actions"].to_i += 1 as
cookies[:"actions"].to_i = cookies[:"actions"].to_i + 1
# and this ^^^^^^^^ doesn't make sense

I am getting error undefined method `to_sym' for nil:NilClass in Rails for updating image?

My controller
def update
handled_error_fields %i(location address1 address2 name name_kanji gender prefecture_code tel zip_code).collect { |s| :"primary_address.#{s}" }
if params[:salon].present?
if params[:salon].present?
if params[:salon][:tel].present?
tel = params[:staff][:tel]
params[:staff][:tel] = NKF.nkf('-W -w -m0 -Z0', tel)
end
end
if params[:staff][:email].present?
email = params[:staff][:email]
email.gsub!(/。/, '.')
params[:staff][:email] = NKF.nkf('-W -w -m0 -Z0', email)
end
end
if params[:staff]["staff_image"].present?
#staff_image = StaffImage.find_by_staff_id(current_staff.id)
if #staff_image.blank?
#staff_image = StaffImage.new
#staff_image.staff_id = current_staff.id
#staff_image.legacy_user_id = current_staff.legacy_user_id
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save!
else
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.update_attribute('image', #staff_image.image)
end
end
super
end
My Model is
class StaffImage < ActiveRecord::Base
end
it has columns
staff_id,
image,
legacy_client_id.
Real problem is after insertion of image in database, I can't update the image. I am new to Rails. I know problem is in this line:
#staff_image.update_attribute('image', #staff_image.image)
Not using any attachment plugins? Have a look on https://github.com/thoughtbot/paperclip gem. Way too easy for handle this kind of things in Rails.
Not necessary to use update_attribute method. Simple save could solve.
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save
You might want to try calling "with_indifferent_access" like:
params = params.with_indifferent_access
before accessing "staff_image"
params[:staff]["staff_image"]["image"]
this should get rid of the error and then:
#staff_image.image = params[:staff]["staff_image"]["image"].read
#staff_image.save

How to get net salary value from database in rails 4

I am having problem getting net-salary value. I have teacher_payslip model. For calculating net-salary,I have written callback.
In TeacherPayslip.rb
#callbacks
after_create :net_salary
def net_salary
#teacher_id = self.id
#da = (self.basic * self.da)/100
#hra = (self.basic * self.hra)/100
#gs = #da + #hra + self.basic
#pf = (#gs * self.pf)/100
#netsalary = #gs - #pf + self.special_allowance + self.bonus
#raise #netsalary.inspect
#a = TeacherPayslip.find(#teacher_id)
#raise #a.inspect
#a.update_attributes(:net_salary => #netsalary)
end
The net_salary value was updated in TeacherPayslip Model.
In Rails console, I have tried some code
TeacherPayslip.last.net_salary
Shows true value instead of net_salary value
I don't know, Why this query shows true value.. Please Help Me...
It's a naming collision. You're overwriting the method net_salary.
The return value of true is the return value of update_attributes.
To fix this rename your method and the callback to set_net_salary.
user it
TeacherPayslip.last.net_salary

Easier way to write If hash includes then - Ruby

I have the following in an initialize method on my model:
#home_phone = contact_hash.fetch('HomePhone')
However, sometimes I need this instead:
#home_phone = contact_hash.fetch('number')
Also, sometimes neither of those will be true and I will need the home_phone attribute to be empty.
How can I write this out without creating a big loop like so:
if contact_hash.has_key?('HomePhone')
#home_phone = contact_hash.fetch('HomePhone')
elsif contact_hash.has_key?('number')
#home_phone = contact_hash.fetch('number')
else
#home_phone = ""
end
You could try
#home_phone = contact_hash.fetch('HomePhone', contact_hash.fetch('number', ""))
or better
#home_phone = contact_hash['HomePhone'] || contact_hash['number'] || ""
contact_hash.values_at('HomePhone','number','home_phone').compact.first
Edit:
My first solution did not really give the answer asked for. Here is a modified version, although I think in the case of only 3 options the solution given by #knut is better.
contact_hash.values_at('HomePhone','number').push('').compact.first
def doit(h, *args)
args.each {|a| return h[a] if h[a]}
""
end
contact_hash = {'Almost HomePhone'=>1, 'number'=>7}
doit(contact_hash, 'HomePhone', 'number') # => 7
You could use values_at I suppose:
#home_phone = contact_hash.values_at('HomePhone', 'number').find(&:present?).to_s
That isn't exactly shorter but it wouldn't be convenient if you had the keys in an array:
try_these = %w[HomePhone number]
#home_phone = contact_hash.values_at(*try_these).find(&:present?).to_s
You could also wrap that up in a utility method somewhere or patch it into Hash.

Rails - Triggering Flash Warning with method returning true

I'm trying to trigger a warning when a price is entered too low. But for some reason, it always returns true and I see the warning regardless. I'm sure there something wrong in the way I'm doing this as I'm really new to RoR.
In model:
def self.too_low(value)
res = Class.find_by_sql("SELECT price ……. WHERE value = '#{value}'")
res.each do |v|
if #{value} < v.price.round(2)
return true
else
return false
end
end
end
In controller:
#too_low = Class.too_low(params[:amount])
if #too_low == true
flash[:warning] = 'Price is too low.'
end
I would write it somewhat different. You iterate over all items, but you are only interested in the first element. You return from inside the iteration block, but for each element the block will be executed. In ruby 1.9.2 this gives an error.
Also i would propose using a different class-name (Class is used to define a class)
So my suggestion:
Class YourGoodClassName
def self.too_low(amount)
res = YourGoodClassName.find_by_sql(...)
if res.size > 0
res[0].price.round(2) < 1.00
else
true
end
end
end
You can see i test if any result is found, and if it is i just return the value of the test (which is true or false); and return true if no price was found.
In the controller you write something like
flash[:warning] = 'Price is too low' if YourGoodClassName.too_low(params[:amount])

Resources