undefined method `reject' for string when reading cookie - ruby-on-rails

I have the following code, basically i want to save a cookie the first time a person submits the form, and the next time read from the cookie to populate the form.
def new
#detail = Detail.new(cookies[:detail])
end
And the create method has
def create
#detail = Detail.new(params[:detail])
if #detail.save
cookies[:detail] = {
value: params[:detail],
expires: 30.days.from_now
}
redirect_to confirmation_path
else
render 'new'
end
end
I get the error:
undefined method `reject' for #<String:0x007fbf5486ac48>

Related

undefined method `map' for nil:NilClass in render action error flash

I have a rails form which takes the rails model FlsCenter and orders them alphabetically to be displayed in a drop down. When none of the fields of the form are filled out, and the form is submitted, the page gets a 500 Server Error in which the following Rails error is displayed:
undefined method `map' for nil:NilClass
Where the map function is in the following view code:
= f.select(:fls_center, #fls_centers.map{|p| [p.name, p.id]}, prompt: "Select a Program Center", selected:#school_application.fls_center)
Where #fls_centers is defined in the new method of my SchoolApplicationController here:
#fls_centers = FlsCenter.order('name ASC')
Here are the relevant controller methods from SchoolApplicationsController
def create
#school_application = SchoolApplication.new(school_application_params)
if #school_application.save_with_payment
redirect_to pay_path(id: #school_application.id)
else
#school_application.errors.full_messages.each do |msg|
flash.now[:error] = msg
end
render action: "new"
end
end
And here is my new method:
def new
if application_params
#school_application = SchoolApplication.new(application_params)
else
#school_application = SchoolApplication.new()
end
Rails.logger.debug(#fls_centers)
#fls_centers = FlsCenter.order('name ASC')
end
The only thing I can imagine that is going wrong is that render action: "new" does not execute the variable instantiation inside the new method. I do not know how to amerliorate this situation. Thank you
You are executing Rails.logger.debug(#fls_centers) before defining the #fls_centers, So make changes like shown below:
def new
#fls_centers = FlsCenter.order('name ASC')
if application_params
#school_application = SchoolApplication.new(application_params)
else
#school_application = SchoolApplication.new()
end
Rails.logger.debug(#fls_centers)
end
Hope it helps!
You guessed right. The actual new method does not get executed when you call
render action: "new"
You will have to call the variable instantiations all over again:
def create
#school_application = SchoolApplication.new(school_application_params)
if #school_application.save_with_payment
redirect_to pay_path(id: #school_application.id)
else
#school_application.errors.full_messages.each do |msg|
flash.now[:error] = msg
end
#fls_centers = FlsCenter.order('name ASC')
render action: "new"
end
end
If you have a lot of them it might be better to refactor them in a method and call that method in the new method as well as before the render call.

Ruby: Object not instantiated by new method with an initialize method

Use case: Upload and process a csv file and record the upload session in the database.
Approach: Create a model to hold data about the upload session and a controller with a new method that collects the csv file and a create method that creates, populates and saves an upload object.
Problem: The model includes an initialize method (see Model code) that seems to have the necessary information to initialize the object (see debug output), but, when the controller attempts to use the model's new method, the attempt does not result in a useful object (see controller code and debug output).
Question: What do I need to change to create the call_history_upload object?
Ruby 1.9.3 on Rails 3.2.13 on Windows 8.1
Model Code:
class CallHistoryUpload < ActiveRecord::Base
attr_accessible :file_name, :user_id, :record_count, :international_call_count, :unknown_client_count
has_many :call_histories, dependent: :destroy
require 'csv'
def initialize( file_name, user_id )
logger.debug( "CallHistoryUpload.initialize start")
logger.debug( " call_history_file = " + file_name )
logger.debug( " user_id = " + user_id )
#file_name = file_name
#user_id = user_id
#record_count = 0
#international_call_count = 0
#unknown_client_count = 0
logger.debug( "CallHistoryUpload.initialize end")
end
end
Controller code:
class CallHistoryUploadsController < ApplicationController
def get_client_id
-1
end
# GET /call_history_uploads/new
# GET /call_history_uploads/new.json
def new
#call_history_upload = CallHistoryUpload.new( "Unknown", session[:user_id] ) # Needed to suppoprt json
respond_to do |format|
format.html # new.html.erb
format.json { render json: #call_history_upload }
end
end
# POST /call_history_uploads
# POST /call_history_uploads.json
def create
logger.debug( "CallHistoryUploadsController start")
#call_history_upload = CallHistoryUpload.new( params[:call_history_file].original_filename, session[:user_id] )
logger.debug( "CallHistoryUploadsController after instantiation")
<<This is line 24>>logger.debug( "call_history_upload.file_name = " + #call_history_upload.file_name )
respond_to do |format|
if #call_history_upload.save
format.html { redirect_to #call_history_upload, notice: 'Call history upload was successful.' }
format.json { render json: #call_history_upload, status: :created, location: #call_history_upload }
else
format.html { render action: "new" }
format.json { render json: #call_history_upload.errors, status: :unprocessable_entity }
end
end
end
end
log output:
Started POST "/call_history_uploads" for 127.0.0.1 at 2014-11-30 08:40:27 -0500
Processing by CallHistoryUploadsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"iDugtKa8b/U9q71Gk86sJMK6hnX1gvgQt496PX2q4Oo=", "call_history_file"=>#<ActionDispatch::Http::UploadedFile:0x4717788 #original_filename="Test_kiyvivzokpysxilfoftavyuftot.csv", #content_type="application/vnd.ms-excel", #headers="Content-Disposition: form-data; name=\"call_history_file\"; filename=\"Test_kiyvivzokpysxilfoftavyuftot.csv\"\r\nContent-Type: application/vnd.ms-excel\r\n", #tempfile=#<File:C:/Users/Gene/AppData/Local/Temp/RackMultipart20141130-5144-yn8i9>>, "commit"=>"Submit"}
CallHistoryUploadsController start
CallHistoryUpload.initialize start
call_history_file = Test_kiyvivzokpysxilfoftavyuftot.csv
user_id = KinteraAdmin
CallHistoryUpload.initialize end
CallHistoryUploadsController after instantiation
Completed 500 Internal Server Error in 0ms
NoMethodError (undefined method `has_key?' for nil:NilClass):
app/controllers/call_history_uploads_controller.rb:24:in `create'
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (0.0ms)
Oh god, what a mess... You should use composition instead of inheritance. A first refactoring could be:
class CallHistoryUpload < SimpleDelegator
class Model < ActiveRecord::Base
has_many :call_histories, dependent: :destroy
end
def initialize(file_name, user_id)
logger.debug( 'CallHistoryUpload.initialize start')
logger.debug( " call_history_file = #{file_name}" )
logger.debug( " user_id = #{user_id}" )
super( new_model(file_name, user_id) )
logger.debug( "CallHistoryUpload.initialize end")
end
def model
__getobj__
end
def self.create(file_name, user_id)
logger.debug('CallHistoryUploadsController start')
chu = self.new(file_name, user_id)
logger.debug( 'CallHistoryUploadsController after instantiation')
logger.debug( "call_history_upload.file_name = #{chu.file_name}")
return chu
end
private
def new_model(file_name, user_id)
self.class::Model.new({
file_name: file_name,
user_id: user_id,
record_count: 0,
international_call_count: 0,
unknown_client_count: 0,
})
end
end
In the controller we change only the creation:
# POST /call_history_uploads
# POST /call_history_uploads.json
def create
#call_history_upload = CallHistoryUpload.create( params[:call_history_file].original_filename, session[:user_id] )
# rest of the code
If you use something like form_for you may want to pass the #call_history_upload.model to it.
Always try to put as little logic as possible in the controller and to encapsulate it in some object :)
Part of the problem seems to be that you're overriding the normal behavior of ActiveRecord::Base on initialize. An active record object allows you to populate an object's properties like so MyObject.new(property: 'value')
Either remove the initialize method from your object and instantiate your object using
file_name = params[:call_history_file].original_filename
user_id = session[:user_id]
CallHistoryUpload.new(file_name: file_name, user_id: user_id)
or
Call super from within your initialize method to allow ActiveRecord::Base to do its thing like so
def initialize(file_name, user_id)
logger.debug( "CallHistoryUpload.initialize start")
logger.debug( " call_history_file = " + file_name )
logger.debug( " user_id = " + user_id )
#record_count = 0
#international_call_count = 0
#unknown_client_count = 0
super(file_name: file_name, user_id: user_id)
logger.debug( "CallHistoryUpload.initialize end")
end
I'd recommend the first approach as it cleans up your model. If you need to assign default values on the instance of the model, I'd recommend creating a class method with a descriptive name which sets this values on the call to new doing the same assignment as on the first approach. Using an after_initialize call back would also be another option to set defaults but be aware of the consequences of it.
I'd really recommend reading the Getting Started guide to Rails if you're new and are trying to get used to Rails conventions.

Rspec method create error

i try to test method create in my controller:
def create
#fund = Fund.new({started_at: Date.strptime(params[:fund].delete(:started_at), '%m/%d/%Y')}.merge(fund_params))
if #fund.save
flash[:alert] = "Fund #{#fund.name} saved!"
redirect_to funds_path
else
flash[:error] = "Fund #{#fund.name} could not be saved"
render :edit
end
end
file spec:
it 'Can create a new fund' do
fund = FactoryGirl.create(:fund)
post :create
expect(response).to redirect_to(funds_path)
end
And show this error:
NoMethodError: undefined method `delete' for nil:NilClass
The error is in this line, for the method 'delete':
#fund = Fund.new({started_at: Date.strptime(params[:fund].delete(:started_at),...
i don't know how solve this problem, Thanks.
As the error message says, that's because params[:fund] is nil. Try to send the proper parameters to the create action:
post :create, fund: { add_here_needed_params_for_this_action }
Example:
post :create, fund: { started_at: Date.today }

How to show session variable in my controller's method

I have controller's POST action method :
def appinfo
puts session[:arr]
u = User.find_by(apikey: appliance_params[:apikey], id: appliance_params[:id])
if u
render json: session[:arr]
#session[:arr] = nil
puts session[:arr]
else
render json: "UserError : error, i haven't found such user with this params :("
end
end
but also a wrote this code
skip_before_filter :verify_authenticity_token, :only => [:appinfo]
I send POST request to .../appinfo.
And if i want to puts session[:arr] in my method appinfo, it is give me nothing
How can i get session[:arr] ?:

Undefined method `errors'

I have this code in my update action of Registration controller. And I get undefined method 'errors'. I can not use flash message here for some reason.
if subjects_selected.blank?
#registration = Registration.where(:student_id => params[:registration][:student_id], :semester_id => params[:registration][:semester_id] )
redirect_to editreg_registrations_path(#registration.first.id, params[:registration][:student_id], params[:registration][:semester_id]), #registration.errors.add(:You_have_to_register_for_at_least_one_subject) and return
end
How can I access error method here?
you can take the method in Registration model for error displaying the errors
like
error_array = Registration.validate_subjects(params[:registration][:student_id],params[:registration][:semester_id])
then in Registration model
def validate_subjects(student_id, semester_id)
is_registration = self.where(:student_id=>student_id,:semester_id =>semester_id)
error_array=[]
if !is_registration
//RIGHT THE CODE
error_array << "You_have_to_register_for_at_least_one_subjec"
end
error_array
end
if subjects_selected.blank?
#registration = Registration.where(:student_id => params[:registration][:student_id], :semester_id => params[:registration][:semester_id] )
if !#registration.errors
redirect_to editreg_registrations_path(#registration.first.id, params[:registration][:student_id], params[:registration][:semester_id])
else
#registration.errors.add(:You_have_to_register_for_at_least_one_subject)
end
end

Resources