interning empty string error - ruby-on-rails

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

Related

How to append an array in parameters after Rails form submit?

I have a form with checkboxes that get passed as an array "list_person_ids" on form submit. My models are "Occurance" which has an n:m relationship with "ListPerson" through the Model "Person". "list_person_ids" are saved in Person with the Occurance id and the ListPerson id.
I want to append one or more values to the array before this gets saved. The reason I need to do this is because the user can also add a new value in ListPerson using a textbox with the name "person_name".
def create
#occurance = Occurance.new(occurance_params)
add_person_id(#occurance)
...
# save
end
def add_person_id(object)
if params[:person_check] == '1'
object.list_person_ids.push( ListPerson.find_or_create_by(person: params[:person_name]).id )
end
end
def occurance_params
params.require(:occurance).permit(:person_check, :person_name, dim_person_ids: [])
end
find_or_create_by is successful, but nothing gets pushed to the array "list_person_ids". There is also no error message. Do I have to give permission somewhere to append this array? Please let me know if some information is missing.
on your model you can do something like below:
....
before_create :create_lists
private
def create_lists
ListPerson.find_or_create_by(list_person_ids: person_name.id)
end

Build array of objects from params hash after Transaction block fails, Rails

I have a form where a user can update multiple resources at the same time. The transaction block makes the form atomic: if one validation fails for any of the resources being updated, then none of the resources get updated, and active record rollsback all changes.
When transaction fails, I want to render the form again, display the same input that the user entered along with errors next to each of the error input fields which prevented the transaction from going through.
The transaction block works. What I am having trouble with is building the array of objects from the params log. Each index of the array should contain a hash which holds key/value pairs of all the attributes of a specific resource.
UDPATE: BELOW IS THE ANSWER CODE THANKS TO THE RESPONSES
Code:
def update_multiple
begin
User.transaction do
params[:users].each do |k, v|
User.find(k).update!(v)
end
flash[:notice] = "Update Successful"
redirect_to :users and return
end
rescue
#users = []
params[:users].each do |k,v|
#users.push(User.new({:id => k}.merge(v)))
end
flash[:error] = "Errors found"
render :edit_multiple and return
end
end
And for good measure, here is what the passed in parameters looks like in the log. This transaction fails because the name attribute must be at least 3 characters long.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xyz=", "users"=>{"15"=>
{"name"=>"Neil", "age"=>"11"}, "16"=>{"name"=>"z", "age"=>"33"}, "17"=>
{"name"=>"John", "age"=>"99"}}, "commit"=>"Submit Changes"}
Thanks in advance! Any way to write this code better in ruby is much appreciated as well.
Ok, so you're trying to iterate through a list of objects in your params using a for_each and an external iterator, you really don't want to do that. I'd suggest something like this:
params[:users].each do |k,v|
# k is the "key" of each user while v is the values associated with each key
#users.push(User.new(:id => k, v)
# I'm doing this in my head so you might need:
# #users.push(User.new({:id => k}.merge(v))
# if you start getting errors about looking for a proper hash or something
# I can't remember how good Rails/Ruby is at recognizing nested hashes
end
That should produce a new user for each user object passed in using the ID provided and the values associated with each value.

Rails Cookie Issue

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

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

Sending Simple Email in Rails

I've read a few questions and http://guides.rubyonrails.org/action_mailer_basics.html on how to send emails with Rails but can't seem to get it to work within the context of my current application.
I had an existing emailer.rb with a couple of methods that were identical apart from the parameters they accepted were named differently so I copied their format:
def quotation_notification(q)
#recipients = q.recipient_email
#from = q.partner_name + "<#{q.partner_email}>"
#subject = "New Quotation from " + q.partner_name
#body[:q] = q
end
I then created a new view file in emailers named quotation_notification.rhtml which just contains text for the moment.
I am then calling the function from inside a different controller and sending hardcoded parameters for now:
q = QuotationEmail.new(:recipient_email => 'martin#domain.co.uk', :partner_name => 'Martin Carlin', :partner_email => 'martin#domain.co.uk')
# send email
Emailer.deliver_quotation_notification(q)
Then finally, I created a new model for QuotationEmail
class QuotationEmail
def initialize(recipient_email, partner_name, partner_email)
#recipient_email = recipient_email
#partner_name = partner_name
#partner_name = partner_email
end
end
The error I get is ArgumentError (wrong number of arguments (1 for 3))
Eventually I'll be sending more parameters and hopefully attaching a pdf aswell but just trying to figure out why this isn't working first.
You are getting this error because while initialising QuotationEmail object though you think you're passing 3 params you're essentially passing only one parameter which is a hash. And initialize is expecting 3. See example below
class A
def initialize(a,b=1,c=2)
puts a
puts b
puts c
end
end
a = A.new(:recipient_email => 'martin#domain.co.uk', :partner_name => 'Martin Carlin', :partner_email => 'martin#domain.co.uk')
#=> {:recipient_email=>"martin#domain.co.uk", :partner_name=>"Martin Carlin", :partner_email=>"martin#domain.co.uk"}
#=> 1
#=> 2
If you're trying to use named parameters instead you'd need to redefine your initialize as
def initialize(recipient_email:a,partner_name:b,partner_email:c)
and invoke it as below -
a = A.new(recipient_email:'martin#domain.co.uk', partner_name:'Martin Carlin', partner_email:'martin#domain.co.uk')

Resources