Problem with Twitter search api - ruby-on-rails

working when using this in rails c
client = TwitterSearch::Client.new('campvote')
tweets = client.query('#barcampmlk2 #railsforzombies +1')
but not when BarcampSession.update_twitter! it retune empty hash
require 'twitter_search'
class BarcampSession < ActiveRecord::Base
validates :hash_tag , :format => {:with => /^#\w+/ } , :presence => true ,:uniqueness => true
validates :name , :presence => true
validates :email , :presence => true , :format => {:with => /((\S+)#(\S{3}[a-zA-z0-9)]\S*))/ }
validates :handphone, :presence => true
def self.update_twitter!
client = TwitterSearch::Client.new('campvote')
BarcampSession.all.each do |sess|
tweets = client.query('#barcampmlk2 #{sess.hash_tag} +1')
puts tweets.to_yaml
end
end
end
it return
rb(main):014:0> BarcampSession.update_twitter!
--- !seq:TwitterSearch::Tweets []
=> [#<BarcampSession id: 1, hash_tag: "#railsforzombies", name: "wizztjh", email: "wiz123tjh#gmail.com", handphone: "1234006", since: nil, created_at: "2010-12-14 18:28:01", updated_at: "2010-12-14 18:28:01">]

String interpolation works only with double quotes, not single quotes. Change the line
tweets = client.query('#barcampmlk2 #{sess.hash_tag} +1')
to
tweets = client.query("#barcampmlk2 #{sess.hash_tag} +1")

Related

Rails, validations within a with_options block don't work

I have an old Rails 2 app where I have a User model that handles profiles of users coming from web and mobile applications. I would like to have 2 separate groups of validations for web and mobile users. I use DEVISE for authentication.
In order to recognize if a user relates to web or mobile, I use an attr_accessor called validation_for_mobile that I set on the controller side, before saving/updating the record.
It appears that some validations, especially the "validates_length_of :password", get executed even if they are inside a block with_options that should not be evaluated.
Inside the User model I have this code:
# WEB VALIDATIONS
with_options :if => "self.validation_for_mobile == false && !self.remote_sync" do |vm1|
vm1.validates_date :birthday, :allow_blank => true
vm1.validates_presence_of :company, :name, :surname, :address, :city, :province, :postal_code, :position, :company_type, :phone, :unless => :is_imported
vm1.validates_format_of :phone, :with => /\A([0-9]+)\Z/i, :message => 'deve contenere solo numeri', :unless => :is_imported
vm1.validates_presence_of :vat, :if => "!imported && !self.script_imported && company_type != 'individuale' && !company_type.blank?"
vm1.validates_presence_of :social_number, :if => "!imported && !self.script_imported && company_type == 'individuale' && !company_type.blank? "
vm1.validates_presence_of :remote_id, :if => "!came_from_user && !imported && !script_imported"
vm1.validates_acceptance_of :privacy_accepted, :privacy_third_part, :accept => true, :allow_nil => false, :unless => :is_imported
vm1.validates_presence_of :login, :email
vm1.validates_email_format_of :email, :message => "email non valida"
vm1.validates_presence_of :remote_sap_code, :remote_as_code, :if => "!came_from_user"
vm1.validates_uniqueness_of :login, :scope => :branch_id, :case_sensitive => false
vm1.with_options :if => :password_required? do |v|
v.validates_presence_of :password
v.validates_confirmation_of :password
v.validates_format_of :password, :with => /^(?=(.*\d){1})(?=.*[a-zA-Z])[0-9a-zA-Z]+$/i, :message => 'solo lettere e almeno 1 numero!'
v.validates_length_of :password, :within => 6..10, :allow_blank => true
end
end
# MOBILE VALIDATIONS
with_options :if => "self.validation_for_mobile == true && !self.remote_sync" do |vm2|
with_options :if => :mobile_validations do |vm2|
vm2.validates_presence_of :company, :vat, :name, :surname, :phone
vm2.validates_format_of :phone, :with => /\A([0-9]+)\Z/i, :message => 'deve contenere solo numeri'
vm2.validates_length_of :vat, :within => 11..15
vm2.validates_presence_of :login, :email, :branch_id
vm2.validates_email_format_of :email, :message => "email non valida"
vm2.validates_uniqueness_of :login, :scope => :branch_id, :case_sensitive => false
vm2.with_options :if => :password_required? do |v|
v.validates_presence_of :password
v.validates_confirmation_of :password
v.validates_format_of :password, :with => /^(?=(.*\d){1})(?=.*[a-zA-Z])[0-9a-zA-Z]+$/i, :message => 'solo lettere e almeno 1 numero!'
v.validates_length_of :password, :within => 1..10, :allow_blank => true
end
end
Every time I try to create a new user from mobile, I expect only the second block of validations to be evaluated, where "validates_length_of :password" is "within => 1..10"
But I receive the error that password is too short (at least 6 chars). And that's the first block!!!
Can you help me?
I also tried to move the conditions of with_options inside a method, like this:
with_options :if => :web_validations
with_options :if => :mobile_validations
but nothing changed.
This is the code I use to test it:
#user = User.new
#user.company = "Testuser"
#user.vat = "123456789012"
#user.name = "Fafag"
#user.surname = "Fafag"
#user.phone = "9182624"
#user.email = "utentest9876#test.it"
#user.login = "Utentest63"
#user.branch_id = 2
#user.password = "TEST1"
#user.password_confirmation = "TEST1"
#user.plain_password = "TEST1"
#user.mobile_signup = true
#user.mobile = true
#user.validation_for_mobile = true # model custom validation
#user.renew_mobile_token!
#user.came_from_user = true
#user.remote_id = 0
#user.confirmed = nil
#user.active = false
if #user.save
return true
else
puts #user.errors.full_messages.inspect
end
Ok, I solved this puzzle!
It seems nested with_options blocks don't inherit the outer condition. So I had to specify the first condition inside the nested with_option block, like this:
with_options :if => :mobile_validations do |vm2|
vm2.validates_presence_of :company, :vat, :name, :surname, :phone
vm2.validates_format_of :phone, :with => /\A([0-9]+)\Z/i, :message => 'deve contenere solo numeri'
vm2.validates_length_of :vat, :within => 11..15
vm2.validates_presence_of :login, :email, :branch_id
vm2.validates_email_format_of :email, :message => "email non valida"
vm2.validates_uniqueness_of :login, :scope => :branch_id, :case_sensitive => false
vm2.with_options :if => [:password_required?, :mobile_validations] do |v2|
v2.validates_presence_of :password
v2.validates_confirmation_of :password
v2.validates_format_of :password, :with => /^(?=(.*\d){1})(?=.*[a-zA-Z])[0-9a-zA-Z]+$/i, :message => 'solo lettere e almeno 1 numero!'
v2.validates_length_of :password, :within => 1..10, :allow_blank => true
end
end

Rails conditional validation of Zip Code for many countries

I need a model-level validation for Zip codes in USA and Canada. This code makes me feel bad:
zip_regex_usa = %r{\d{5}(-\d{4})?}
zip_regex_canada = %r{[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d}
validates :shipping_zip, :presence => true, :format => { :with => zip_regex_usa }, :if => :shipping_to_usa?
validates :shipping_zip, :presence => true, :format => { :with => zip_regex_canada }, :if => :shipping_to_canada?
validates :billing_zip, :presence => true, :format => { :with => zip_regex_usa }, :if => :billing_to_usa?
validates :billing_zip, :presence => true, :format => { :with => zip_regex_canada }, :if => :billing_to_canada?
def shipping_to_usa?
shipping_country == 'US'
end
def billing_to_usa?
billing_country == 'US'
end
def shipping_to_canada?
shipping_country == 'CA'
end
def billing_to_canada?
billing_country == 'CA'
end
How to make this code more elegant, writing a single validation line for each field?
You can use gem validates_as_postal_code
It allows you to check zip codes like this:
class Person < ActiveRecord::Base
validates_as_postal_code :postal_code, :country => "CA", :allow_blank => true
end
and there're more options
EDIT:
There's also one nice gem: going_postal check it out!
I pulled some bits together into this gem: validates_zipcode.
It currently supports 259 countries zipcode formats and plays nice with Rails 3 & 4.
You can use it like this:
class Address < ActiveRecord::Base
validates_zipcode :zipcode
validates :zipcode, zipcode: true
validates :zipcode, zipcode: { country_code: :ru }
validates :zipcode, zipcode: { country_code_attribute: :my_zipcode }
end

Rails: Strange validation error

I have a Location model with fields:
Location(id: integer, name: string, address: string, latitude: decimal, longitude: decimal, created_at: datetime, updated_at: datetime, rating: decimal, rating_count: integer)
In my location model, i have the following validations (which work fine):
attr_accessible :name, :address, :latitude, :longitude, :rating, :rating_count
validates :name, :presence => true, :length => { :maximum => 50 }
validates :address, :presence => true
validates :rating, :inclusion => 0..5
validates :rating, :presence => { :message => " cannot be blank" }
I also have a Post model with fields:
Post(id: integer, user_id: integer, location_id: integer, info: string, created_at: datetime, updated_at: date time)
And the following validations:
attr_accessible :info, :address, :name, :rating
belongs_to :user
belongs_to :location
attr_accessor :rating, :address, :name #Virtual attributes for the Post create form
validates :name, :presence => true, :length => { :maximum => 50 }
validates :address, :presence => true
validates :rating, :inclusion => 0..5
validates :rating, :presence => { :message => " cannot be blank" }
Now, the issue is that when I try to create a new Post, the validations for name and address work fine (just as they work for Location), but the validation for rating always fails. Even when I enter a rating of '3', I get the error Rating is not included in the list for some reason, although a rating of '3' is validated correctly if used directly with the Location#create action.
Does anyone know why only the rating validation isn't working as expected with Post, even though it works fine with Location, and the other validations behave identically with the two models ?
EDIT: Here's the create action from posts_controller:
def create
#post = current_user.posts.build(params[:post])
#location = Location.find_by_address_and_name(params[:post][:address], params[:post][:name])
if #location.nil?
#location = Location.find_by_address(params[:post][:address])
end
#If the address and the name of the location is the same, just update the rating for that location, and associate the post with the location
if (#location && params[:post][:name] == #location.name)
#post.location_id = #location.id
#location.rating_count += 1
#location.rating = ( (#location.rating + params[:post][:rating].to_r.to_d )/ #location.rating_count )
else
#post.location_id = Location.create(:address => params[:post][:address], :name => params[:post][:name], :rating => params[:post][:rating].to_r.to_d).id
end
#post.save
respond_to do |format|
if #post.save
#location.save! #Update the location only if the post was successful
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
I know this is a LARGE post, but the main point is, 2 identical validations are failing in one place and succeeding in another. One of them validates attributes which are part of the database, the other validates virtual attributes, and I suspect this is the underlying problem.
validates :rating, :inclusion => ['0', '1', '2', '3', '4', '5']
# OR
validates :rating, :inclusion => (0..5).map(&:to_s)
UPD
add this method
def rating=param
#rating = param.to_f
end
so now you can use your original validation
validates :rating, :inclusion => (0..5)
You need to store an integer value 3 in rating, not the string "3".
Something like:
model.rating = params[:rating].to_i

Numericality Validations, Catching nil Values on Comparisons

I have an object that contains a number range and a description [min_val, max_val, name].
I need to validate that min_val < max_val. However, if one of them is blank I get a nil comparison error, instead, I'd like to tell the user that a number is required.
Also, how can I change the error message for numericality?
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :less_than => :max_val}
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :greater_than => :min_val}
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }
You can use :message to specify a custom error message.
validates :max_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validates :min_val, :presence => true, :numericality => {:greater_than => 0, :message => " is an invalid number."}
validate do |record|
record.errors.add_to_base("The min_val should be less than max_val") if min_val.to_i >= max_val.to_i
end
validates :name, :presence => true, :if => Proc.new { |r| !r.min_val.nil? || !r.max_val.nil? }

Rails VALIDATES

I have the following:
validates :fname, :presence => true, :length => { :minimum => 2 }
How do I add a message to that? Right now the errors says "Fname is too short (minimum is 2 characters)" I'd like it to say First Name and not Fname.
thanks?
could you try this?
validates :fname, :presence => true, :length => { :minimum => 2 },
:format => {
:message => 'your message.'}
Solution ended up being:
Change the name of the field in your locale file:
en:
activerecord:
attributes:
user:
fname: First name
validates :fname, :presence => true, :length => { :minimum => 2 }, :message => "your message goes here"
UPDATE
If you want to put a friendly column name use code like this:
class User < ActiveRecord::Base
HUMANIZED_ATTRIBUTES = {
:email => "E-mail address"
}
def self.human_attribute_name(attr)
HUMANIZED_ATTRIBUTES[attr.to_sym] || super
end
end
Other way to solve this problem is to take the approach described in this blog post: http://www.softiesonrails.com/2008/4/23/better-messages-for-activerecord-validation-errors

Resources