Rails Cookie Issue - ruby-on-rails

I have the following new method in a ruby on rails app:
def new
if cookies[:owner].empty?
cookies[:owner] = SecureRandom.hex
end
#movie = Movie.new
#movie.owner = cookies[:owner]
end
Basically, each new user is supposed to be issued a code which identifies them (though just by the cookie). So when the user creates a movie, the cookie that was created is stored in the owner field.
So two problems:
Using the .empty? method when I delete the cookie from the browser, returns a undefined methodempty?' for nil:NilClass`
When I do have a cookie already set in the browser, and then create a movie, the cookies[:owner] value is different from the #movie.owner code?

cookies[:owner] will either be nil (when it hasn't been set), or a String (when it's been set). The method you're looking for is blank?, instead of empty?
2.1.0 :003 > nil.blank?
=> true
2.1.0 :005 > "i'm not blank".blank?
=> false
2.1.0 :006 > " ".blank?
=> true
As for your second problem: where do you call the save method? Do you have any callback on the Movie model that could rewrite the owner attribute?

You could also use this.
def new
if !cookies[:owner]
cookies[:owner] = SecureRandom.hex
end
#movie = Movie.new
#movie.owner = cookies[:owner]
end

Related

Undefined new_record? Ruby Rails

I am trying to check if the domain host url record exist in the domain table before creating it again, but I am getting this error:
undefined method `new_record?' for #<Domain::ActiveRecord_Relation:0x007f320ed8af80>
The class GetMeta is a service object that is getting initialize when a user enter a URL in a form and click submit. I am taking the URL from the form and calling MetaInspector with it to get more meta informations.
The first part (if) new_record method is working perfectly fine, but is creating duplicate values in the domain table. I tried to create a conditional logic, but I am having this bug that I don't know how to fixed.
class GetMeta
include ActiveModel::Model
def initialize(url)
#url = url
end
def new_record
page = MetaInspector.new(#url)
#domain = Domain.where(:host => page.host)
if new_record?
Domain.create! do |url|
url.root_url = page.root_url
url.scheme = page.scheme
url.host = page.host
url.links.build(url: page.url, title: page.best_title, description: page.description)
end
else
Link.create! do |link|
link.url = page.url
link.title = page.best_title
link.description = page.description
end
end
end
private
def new_record?
#domain.new_record?
end
end
The problem is described by an error. Let's see:
undefined method `new_record?' for
#<Domain::ActiveRecord_Relation:0x007f320ed8af80>
The problem is the line
#domain = Domain.where(:host => page.host)
This returns an ActiveRecord relation instead of single record.
You should take a .first or .last.
#domain = Domain.where(:host => page.host).last
That's the fix, but let's see how can we improve the code.
We can use method exists? which is defined in ActiveRecord Relation (docs: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F)
if Domain.exists?(host: page.host)
Link.create! do |link|
link.url = page.url
link.title = page.best_title
link.description = page.description
end
else
Domain.create! do |url|
url.root_url = page.root_url
url.scheme = page.scheme
url.host = page.host
url.links.build(url: page.url, title: page.best_title, description: page.description)
end
end
This way we don't need instance variable #domain and helper method new_record?
You are calling an instance method from within an instance method. So you need to specify which instance you are referring to. You need to use 'self'. So instead of just calling 'new_record?', try calling self.new_record?

How to compare new data with existing in bd before save

Every time, when I'm getting the data from the API request, I require to compare and update records, if any changes was there.
for example i have saved User
user = User.first
user.name => 'name_one'
when i calling to api,api returns me User but name was cahnged to 'name_two'
so i need compare existing user with newly arrived and if name changed replace it
example of calling api
url= 'my api str'
result = Curl.get(url)
JSON.parse(result.body_str).each do |key, value|
value["commissions"].each do |k, v|
User.create(name: v["name"],etc... )
end
end
I will be glad for any suggestions.
You can also try the following:
u = User.first
u.name = "name_two"
u.name_changed? #=> true/false
u.name_was #=> "name_one" if it was "name_one"
These are called dirty method and very helpful for this kind of task.
Thanks
Try this code
u = User.first
u.name = "name_two"
u.save if u.changes.include?("name")
I believe you shall use active record's private method #read_attribute to compare current updated values with stores ones:
if send(:read_attribute, :attr) == self.attr
# value isn't changed
end
Additional info you can read here:
Validation from controller
You shall validate newly created record from controller:
v['name'] = 'User 1'
user = User.create(name: v['name'])
user.name # => # User 1

How to avoid bug if geocoder sends me empty array when retrieving country of user (Rails 4/geocoder)

I am building a daily deal Rails app
I am displaying to the user only the deals of the country i associate him with thanks to geocoder gem.
I wonder what would happen if geocoder fails (for any reason) to retrieve the country and sends an empty array, as i think it does when it fails to send ip( see https://github.com/alexreisner/geocoder#error-handling)
class StaticPagesController < ApplicationController
def home
#deals = deal_in_user_country.featured_on_hp
respond_to do |format|
format.html # home.html.erb
end
end
# create a scope to filter the deals that meet the user's country
def deal_in_user_country
Deal.where(country: set_location_by_ip_lookup.country || 'United States') # if geocoder gets pb then default = US version
end
end
end
As you see, I tried to use || and puts 'United States' but I don't think it will work. i think that if geocoder sends empty array , set_location_by_ip_lookup=[] and then set_location_by_ip_lookup.country will generate an error, am I right ?
How should i avoid bugs when geocoder sends an empty array ?
For info if it helps, here is how I set country in concerns/CountrySetter
module CountrySetter
extend ActiveSupport::Concern
included do
before_filter :set_location_by_ip_lookup
end
def set_location_by_ip_lookup
if Rails.env.development? or Rails.env.test?
Geocoder.search(request.remote_ip).first
else #in production
request.location
end
end
end
Your code should be fine, if geocoder allways returns at least an empty array (except I would not name this mehtod set_ because it's not setting anything)
Try out on irb
{a: [:d].first || :b}
=> {:a=>:d}
{a: [].first || :b}
=> {:a=>:b}
However i would put this in paranethesis to make it clear
Deal.where(country: (set_location_by_ip_lookup.country || 'United States'))
Gecodoer.search shouldn't be throwing exceptions, otherwise it would be named Geocoder.search! according to an unwritten ruby convention. I would double check this by plugin out the internet connection and see what happens

Ruby on rails, multiple check for nil attributes

I'm trying to check multiple attributes for nil, I've found this post simplify... but I'm not getting the results I want. I have a user whom I want to update their profile if needed. This user however has all the data I want.
#user.try(:age_id).nil?
#returns false
#user.try(:customer).nil?
#returns false
#user.try(:country).nil?
#returns false
#user.try(:age_id).try(:customer).try(:country).nil?
#returns true
Why is it responding with true here when all the other single instances of tries responds with false?
You are chaining the .try(), which fails after the try(:age_id):
It tries to call age_id on the #user object
if #user.nil? # => returns nil
if #user.age_id != nil # => returns a Fixnum
Then you call the method try(:customer) on a Fixnum which obviously fails # => returns nil
etc.
An example from the IRB console:
1.9.3p448 :049 > nil.try(:nothing).try(:whatever).try(:try_this_also).nil?
=> true
If you want to test that all of these attributes are not nil, use this:
if #user.present?
if #user.age_id.presence && #user.customer.presence && #user.country.presence
# they are all present (!= nil)
else
# there is at least one attribute missing
end
end

interning empty string error

Currently, in my request model I have:
belongs_to :requestor, :class_name => 'User'
So the requestor is the current_user.
Problem is when the current_user clicks the create button to submit a form for a request, all of the attributes get updated to the database that are in the form.
But since requestor_id is not a value to fill out in the form, that brings back a value of null in the database when the new request record is created.
What I want is an integer (which equates to the primary key of the Users table) updated in the requestor_id column in the request table when the user clicks the create button.
So I thought that maybe adding a requestor_id as a symbol in the params for the create action would solve that:
def create_common
#a = Request.new
b = #a.requestor_id
#resource = yield params[:contact + "#{b}".to_sym]
self.resource = #resource
But instead it returns the following error:
interning empty string
Thanks for any suggestions.
I kept getting this error. I traced it to very simple code and reproduced in the console with this:
ruby-1.8.7-p174 :084 > a = 'fred'
=> "fred"
ruby-1.8.7-p174 :085 > a.to_sym
=> :fred
ruby-1.8.7-p174 :086 > a = ''
=> ""
ruby-1.8.7-p174 :087 > a.to_sym
ArgumentError: interning empty string
from (irb):87:in `to_sym'
from (irb):87
Can you not just pass the Request the current_user when you create it?
#req = Request.new(:requestor => current_user)
I am not quite sure what the yield params statement is meant to be doing,
If I'm understanding your question correctly, you want to assign the current_user's id as the requestor id to the Request model?
# assign values passed in via form
#request = Request.new(params[:request])
# assign current_user to request
#request.requestor = current_user
# save the request
#request.save!
Hope this helps!
I had a '.' in an error message similar to:
errors.add('You entered a non-supported widget.')
and was getting the "interning empty string error"
This post saved me:
http://www.tonyamoyal.com/2009/10/20/interning-empty-string-error-in-ruby-on-rails/
Simply changing to:
errors.add('You entered a non-supported widget')
fixed it. Rails 2.3.4 and Ruby 1.8.5

Resources