How can I add information to custom user field (Devise) - ruby-on-rails

I create a custom field in user (using a Devise) in my Rails project, varible called information. Type is string.
Somethigh like that: current_user.information
How can I add another string to end of this string?
I need a method then do like this:
current_user.information << some_varible
And save changes.

If the value of current_user.information is a string you can append to it like you stated.
s = current_user.information
s << "New string addition"
s.save

Except the << method mentioned on #Rockwell's answer, you can achieve your goal by using String#concat as well:
s = current_user.information
s.concat("New string addition")
s.save

Related

Returning a specific string format from an array

I have an array of Persons (class contain name and lastname and id )
what I have to do is to return a string form this array but in a specific format an example will be more explicative
array=[PERS1,PERS2]
I need this as a return value : "The name of all persons : "+ PERS1.name + PERS1.LASTN + " , " + PERS2.name +PERS2.LASTN +","
I know this method
array.each{ |per|
#but this will not return the format ,and with each I think I can only print (I'm new in the ruby field
}
all of this because I need it when overriding to_s , because I need to provide a string -> to_s
def to_s
"THE name of all preson"+#array.each #will not work as I want
end
Thank you for ur time and effort and if you need any clarification please let me know
each just iterates over a collection and returns the collection itself. You may want to use map and join the result.
array.map { |person| "#{person.name} #{person.lastn}" }.join(',')
Or if you modify your Person class it can be even simpler.
# I assume that the name of the class is Person and name and lastn are always present
class Person
def full_name
"#{person.name} #{person.lastname}"
end
end
# Then you can call this method on `map`.
array.map(&:full_name).join(',')
Try this,
array.each do |per|
"#{per.name} #{per.LASTN}"
end
For more info check Interpolation

Rails - dynamic method creation

I have two methods that are identical apart from the ActiveRecord class they are referencing:
def category_id_find(category_name)
category = Category.find_by_name(category_name)
if category != nil
return category.id
else
return nil
end
end
def brand_id_find(brand)
brand = Brand.find_by_name(brand)
if brand != nil
return brand.id
else
return nil
end
end
Now, I just know there must be a more Railsy/Ruby way to combine this into some kind of dynamically-created method that takes two arguments, the class and the string to find, so I tried (and failed) with something like this:
def id_find(class, to_find)
thing = (class.capitalize).find_by_name(to_find)
if thing.id != nil
return thing.id
else
return nil
end
end
which means I could call id_find(category, "Sports")
I am having to populate tables during seeding from a single, monster CSV file which contains all the data. So, for example, I am having to grab all the distinct categories from the CSV, punt them in a Category table then then assign each item's category_id based on the id from the just-populated category table, if that makes sense...
class is a reserved keyword in Ruby (it's used for class declarations only), so you can't use it to name your method parameter. Developers often change it to klass, which preserves the original meaning without colliding with this restriction. However, in this case, you'll probably be passing in the name of a class as a string, so I would call it class_name.
Rails' ActiveSupport has a number of built in inflection methods that you can use to turn a string into a constant. Depending on what your CSV data looks like, you might end up with something like this:
def id_find(class_name, to_find)
thing = (class_name.camelize.constantize).find_by_name(to_find)
...
end
If using a string, you can use constantize instead of capitalize and your code should work (in theory):
thing = passed_in_class.constantize.find_by_name(to_find)
But you can also pass the actual class itself to the method, no reason not to:
thing = passed_in_class.find_by_name(to_find)

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.

If string is empty then return some default value

Often I need to check if some value is blank and write that "No data present" like that:
#user.address.blank? ? "We don't know user's address" : #user.address
And when we have got about 20-30 fields that we need to process this way it becomes ugly.
What I've made is extended String class with or method
class String
def or(what)
self.strip.blank? ? what : self
end
end
#user.address.or("We don't know user's address")
Now it is looking better. But it is still raw and rough
How it would be better to solve my problem. Maybe it would be better to extend ActiveSupport class or use helper method or mixins or anything else. What ruby idealogy, your experience and best practices can tell to me.
ActiveSupport adds a presence method to all objects that returns its receiver if present? (the opposite of blank?), and nil otherwise.
Example:
host = config[:host].presence || 'localhost'
Phrogz sort of gave me the idea in PofMagicfingers comment, but what about overriding | instead?
class String
def |(what)
self.strip.blank? ? what : self
end
end
#user.address | "We don't know user's address"
Since you're doing this in Ruby on Rails, it looks like you're working with a model. If you wanted a reasonable default value everywhere in your app, you could (for example) override the address method for your User model.
I don't know ActiveRecord well enough to provide good code for this; in Sequel it would be something like:
class User < Sequel::Model
def address
if (val=self[:address]).empty?
"We don't know user's address"
else
val
end
end
end
...but for the example above this seems like you'd be mixing view logic into your model, which is not a good idea.
Your or method might have some unwanted side-effects, since the alternative (default) value is always evaluated, even if the string is not empty.
For example
#user.address.or User.make_a_long_and_painful_SQL_query_here
would make extra work even if address is not empty. Maybe you could update that a bit (sorry about confusing one-liner, trying to keep it short):
class String
def or what = ""
self.strip.empty? ? block_given? ? yield : what : self
end
end
#user.address.or "We don't know user's address"
#user.address.or { User.make_a_long_and_painful_SQL_query_here }
It is probably better to extend ActiveRecord or individual models instead of String.
In your view, you might prefer a more explicit pattern like
#user.attr_or_default :address, "We don't know the user's address"
Ruby:
unless my_str.empty? then my_str else 'default' end
RoR:
unless my_str.blank? then my_str else 'default' end
I recommend to use options.fetch(:myOption, defaultValue) because it works great with boolean flags like the ones mentioned above and therefore seems better to use in general.
Examples
value = {}
puts !!(value.fetch(:condition, true)) # Print true
value = {}
value[:condition] = false
puts !!(value.fetch(:condition, true)) # Print false
value = {}
value[:condition] = true
puts !!(value.fetch(:condition, true)) # Print true
value = {}
value[:condition] = nil
puts !!(value.fetch(:condition, true)) # Print false

How do I convert a string to a class method?

This is how to convert a string to a class in Rails/Ruby:
p = "Post"
Kernel.const_get(p)
eval(p)
p.constantize
But what if I am retrieving a method from an array/active record object like:
Post.description
but it could be
Post.anything
where anything is a string like anything = "description".
This is helpful since I want to refactor a very large class and reduce lines of code and repetition. How can I make it work?
Post.send(anything)
While eval can be a useful tool for this sort of thing, and those from other backgrounds may take to using it as often as one might a can opener, it's actually dangerous to use so casually. Eval implies that anything can happen if you're not careful.
A safer method is this:
on_class = "Post"
on_class.constantize.send("method_name")
on_class.constantize.send("method_name", arg1)
Object#send will call whatever method you want. You can send either a Symbol or a String and provided the method isn't private or protected, should work.
Since this is taged as a Ruby on Rails question, I'll elaborate just a little.
In Rails 3, assuming title is the name of a field on an ActiveRecord object, then the following is also valid:
#post = Post.new
method = "title"
#post.send(method) # => #post.title
#post.send("#{method}=","New Name") # => #post.title = "New Name"
Try this:
class Test
def method_missing(id, *args)
puts "#{id} - get your method name"
puts "#{args} - get values"
end
end
a = Test.new
a.name('123')
So the general syntax would be a.<anything>(<any argument>).

Resources