Why am I getting undefined method 'save' error? - ruby-on-rails

My code is this
def footstamp
if current_user
#user = User.find(params[:id])
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id)
if #tracking
#tracking.accessed_at = Time.now
#tracking.save
else
#tracking = Tracking.new
#tracking.user_id = current_user.id
#tracking.target_user_id = #user.id
#tracking.accessed_at = Time.now
#tracking.save
end
end
end
Then I get this error
NoMethodError (undefined method `save' for []:ActiveRecord::Relation):

Use:
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first

You are getting this error because the result of your method do not return a Tracking, but an array of Trackings.
Either you introduce more conditions to match only one Tracking, or use the first method or iterate over the results,
To use first:
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first
Iterate:
Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).each do |tracking|
if tracking
tracking.accessed_at = Time.now
tracking.save
else
tracking = Tracking.new
tracking.user_id = current_user.id
tracking.target_user_id = #user.id
tracking.accessed_at = Time.now
tracking.save
end
end

Optimised answer,
def footstamp
if current_user
#user = User.find(params[:id])
#tracking = Tracking.where(:user_id => current_user.id, :target_user_id => #user.id).first_or_create
#tracking.accessed_at = Time.now
#tracking.save
end
end
More usefull methods here

Related

How to get rid off underscore "_" from the rails generated url?

I just implemented friendly_id on the category model of rails app. Earlier it used to generate url like this:
localhost/search?category_id=208. Now I got it to generate url as below
localhost:3000/search?category_id=metal-processing-and-machine-tool
The url generating line is:
<a href="<%= search_equipments_path(:category_id => category.slug ) %>">
The search_equipments method is as follows:
def search_equipments
begin
if (params.keys & ['category_id', 'sub_category', 'manufacturer', 'country', 'state', 'keyword']).present?
if params[:category_id].present?
#category = Category.active.find params[:category_id]
else
#category = Category.active.find params[:sub_category] if params[:sub_category].present?
end
#root_categories = Category.active.roots
#sub_categories = #category.children.active if params[:category_id].present?
#sub_categories ||= {}
#countries = Country.active.all
#manufacturers = Manufacturer.active.all
#states = State.active.where("country_id = ?", params[:country]) if params[:country].present?
#states ||= {}
unless params[:category_id].present? && params[:sub_category].present?
params[:category_id] = #category.id if params[:category_id].present?
params[:sub_category] = #category.id if params[:sub_category].present?
end
#equipments = Equipment.active.filter(params.slice(:manufacturer, :country, :state, :category_id, :sub_category, :keyword)).order("#{sort_column} #{sort_direction}, created_at desc")
else
redirect_to root_path
end
rescue Exception => e
redirect_to root_path, :notice => "Something went wrong!"
end
end
Because of SEO reasons the people above me are telling to get rid off the _ which is in category_id from the url. I tried by changing the format in url generating line. Didn't help. Can please anyone tell me if it is doable and how can I achieve that?
Please let me know in the comments if any extra information needed.

RAILS: db count is always 0 in spec

Here is a simple case of spec in Rails 4.2:
it "returns redirect to Save & Copy" do
user_access = FactoryGirl.create(:user_access, :action => 'create', :resource =>'simple_orderx_orders', :role_definition_id => #role.id, :rank => 1,
:sql_code => "")
session[:user_id] = #u.id
q1 = FactoryGirl.create(:simple_orderx_order)
q = FactoryGirl.attributes_for(:simple_orderx_order)
FactoryGirl.create(:project_misc_definitionx_misc_definition, :resource_id => q1.id, :resource_string => 'simple_orderx_orders', definition_category: 'production_step')
expect {
get 'create', {:order => q, commit: I18n.t('Save & Copy')}
expect(response).to redirect_to URI.escape(SUBURI + "/view_handler?index=0&msg=Successfully Saved!")
}.to change(ProjectMiscDefinitionx::MiscDefinition.all.reload, :count).by(1)
end
end
In debugger, there is a new record being added to table MiscDefinition and MiscDefinition.all.count is 2, but in spec the ProjectMiscDefinitinox::MiscDefinition.all.count is always 0 and the spec case fails. What could cause the counting error in spec?
Here is the create in controller:
def create
#order = SimpleOrderx::Order.new(new_params)
#order.last_updated_by_id = session[:user_id]
#order.entered_by_id = session[:user_id]
#order.fort_token = session[:fort_token]
copy_steps(#order) if params[:commit] == I18n.t('Save & Copy') #copy mfg steps from previous order
if #order.save
copy_steps(#order.reload) if params[:commit] == I18n.t('Save & Copy') #copy mfg steps from previous order
redirect_to URI.escape(SUBURI + "/view_handler?index=0&msg=Successfully Saved!")
else
#erb_code = find_config_const('order_new_view', session[:fort_token], 'simple_orderx')
flash[:notice] = t('Data Error. Not Saved!')
render 'new'
end
end
def copy_steps(order)
obj = Order.where('drawing_num = ? AND id != ?', order.drawing_num, order.id).order('created_at DESC') if order.drawing_num.present? #find the previous order of the same drawing#
obj = Order.where('part_num = ? AND id != ?', order.part_num, order.id).order('created_at DESC') if obj.blank? && order.part_num.present?
obj = Order.where('part_name Like ? AND id != ?', "%#{order.part_name}%", order.id).order('created_at DESC') if obj.blank? && order.part_name.present?
copied = false
obj.limit(4).each do |o|
SimpleOrderx.production_step_class.where('resource_id = ? AND resource_string = ? AND definition_category = ?', o.id, params[:controller].sub('/', '_'), 'production_step').each do |r|
new_step = SimpleOrderx.production_step_class.new()
new_step = r.dup
new_step.resource_id = order.id
begin
new_step.save
copied = true
rescue => e
flash[:notice] = 'Error in copying production steps: ' + e.message
end
end
return if copied
end if obj.present?
end

Podio Ruby Rails shows "nomethoderror"

I'm having problems with the Podio_rails_sample. I've included my leadsController and leads.rb files. The line that gets hung up is field['config']['settings']['allowed_values'].
Line 25 is the problematic one:
NoMethodError in LeadsController#new
undefined method `[]' for nil:NilClass
Extracted source (around line #25):
23 app = Podio::Application.find(APP_ID)
24 field = app.fields.find { |field| field['external_id'] == 'status' }
25 field['config']['settings']['allowed_values']
26 end
27
28 def self.create_from_params(params)
Rails.root: c:/Sites/podio_rails_sample
app = Podio::Application.find(APP_ID)
field = app.fields.find { |field| field['external_id'] == 'status' }
field['config']['settings']['allowed_values']
end
def self.create_from_params(params)
Rails.root: c:/Sites/podio_rails_sample
-----------------------------------
class LeadsController < ApplicationController
before_filter :load_collections, :only => [:new, :edit]
def index
#leads = Lead.all
end
def new
#lead = Lead.new
end
def create
Lead.create_from_params(params['lead'])
redirect_to leads_path, :notice => 'Lead created'
end
def edit
#lead = Lead.find_basic(params[:id])
end
def update
Lead.update_from_params(params[:id], params['lead'])
redirect_to leads_path, :notice => 'Lead updated'
end
def destroy
Lead.delete(params[:id])
redirect_to leads_path, :notice => 'Lead deleted'
end
#protected
def load_collections
#lead_contacts = Lead.space_contacts
#sales_contacts = Lead.users
#statuses = Lead.statuses
end
end
-------------------------------------
- leads.rb file
class Lead < Podio::Item
APP_ID =12328033
SPACE_ID =3204114
# Find all items in the Leads app
def self.all
collection = self.find_all(APP_ID)
collection[:all]
end
# Find valid lead contacts in the space
def self.space_contacts
Podio::Contact.find_all_for_space(SPACE_ID, :order => 'contact', :limit => 12, :contact_type => 'space,connection', :exclude_self => false) rescue []
end
# Find valid sales contacts in the space
def self.users
Podio::Contact.find_all_for_space(SPACE_ID, :order => 'contact', :limit => 12, :contact_type => 'user', :exclude_self => false) rescue []
end
# Find valid statuses
def self.statuses
app = Podio::Application.find(APP_ID)
field = app.fields.find { |field| field['external_id'] == 'status' }
field['config']['settings']['allowed_values']
end
def self.create_from_params(params)
# raise fields.inspect
self.create(APP_ID, { :fields => fields_from_params(params) })
end
def self.update_from_params(id, params)
self.update(id, { :fields => fields_from_params(params) })
end
#
# Map the field values return by the Podio API to simple getters
#
def organization
field_values_by_external_id('company-or-organisation', :simple => true)
end
def lead_contact
field_values_by_external_id('contacts', :simple => true).try(:[], 'name')
end
def sales_contact
field_values_by_external_id('sales-contact', :simple => true).try(:[], 'name')
end
def potential_revenue_value
field_values_by_external_id('potential-revenue').try(:first).try(:[], 'value').to_i
end
def potential_revenue_currency
field_values_by_external_id('potential-revenue').try(:first).try(:[], 'currency')
end
def probability
field_values_by_external_id('probability-of-sale', :simple => true)
end
def status
field_values_by_external_id('status', :simple => true)
end
def followup_at
field_values_by_external_id('next-follow-up').try(:first).try(:[], 'start').try(:to_datetime)
end
protected
def field_values_by_external_id(external_id, options = {})
if self.fields.present?
field = self.fields.find { |field| field['external_id'] == external_id }
if field
values = field['values']
if options[:simple]
values.first['value']
else
values
end
else
nil
end
else
nil
end
end
def self.fields_from_params(params)
{
'company-or-organisation' => params[:organization],
'contacts' => (params[:lead_contact].present? ? params[:lead_contact].to_i : nil),
'sales-contact' => (params[:sales_contact].present? ? params[:sales_contact].to_i : nil),
'potential-revenue' => { :value => params['potential_revenue_value'], :currency => params['potential_revenue_currency'] },
'probability-of-sale' => params[:probability].to_i,
'status' => params[:status],
'next-follow-up' => DateTime.new(params['followup_at(1i)'].to_i, params['followup_at(2i)'].to_i, params['followup_at(3i)'].to_i).to_s(:db)
}.delete_if { |k, v| v.nil? }
end
end

How do I pass an array to another action in a controller?

I created a array in start for displaying the IDs one by one, and I want to the same array used in another action called next. In start I created a array called ques. I want to use ques in next.
START:
class AnswersController < ApplicationController
def start
#user = current_user
#student = Student.find_by_admission_no(#user.username)
#exam_group = ExamGroup.find_by_id(params[:exam_group_id])
#answer = Answer.new(params[:ans])
#module = params[:student_additional_field]
#questions = shuf_order(#exam_group,#module)
ques = []
#questions.each do |a|
ques.push q.id unless q.id.nil?
end
a = ques.first
#s = 1
#ans = Question.find_by_id(a)
render(:update) do |page|
page.replace_html 'main', :partial => 'ans', :object => #ans
page.replace_html 'quespan', :partial => 'ques'
end
end
Next:
def next
#user = current_user
#student = Student.find_by_admission_no(#user.username)
#exam_group = ExamGroup.find_by_id(params[:exam_group_id])
#answer = Answer.new(params[:ans])
#answer.answer = params[:answer]
#answer.exam_group_id = #exam_group.id
#answer.user_id = #user.id
passed_question = params[:passed_question]
#answer.questions_id = passed_question
#question = Question.find_by_id(passed_question)
#module = Question.find_by_sql ["SELECT student_additional_field_id FROM questions WHERE id=#{passed_question}"]
student_additional_field_id = #module[0].student_additional_field_id
#questions = shuf_order(#exam_group,student_additional_field_id)
a = #questions.first
#answer.modules_id = student_additional_field_id
if #answer.save
#ans = Question.find_by_id(a, :conditions => [' id not in (?)',answered])
unless #ans.nil?
render(:update) do |page|
page.replace_html 'main', :partial => 'ans', :object => #ans
end
else
render(:update) do |page|
page.replace_html 'main', :partial => 'ans2'
end
end
end
end
The usual way to pass variables between actions is the flash variable.
In start:
flash[:ques] = []
flash[:ques].push 'whatever'
In next:
flash[:ques]
to access the saved var.
But in your case maybe you want to save your ques in session or DB to use ques in more than these 2 actions:
In start:
session[:ques] = []
session[:ques].push 'whatever'
In next:
session[:ques]
Or in DB, you maybe would need a new table.

undefined method `empty?' for nil:NilClass

I display an array of hours in a dropdown field
[["09:30am", "2013-02-14 09:30:00"], ["10:00am", "2013-02-14 10:00:00"] ...
I render the array with:
<%= f.select :atime, #time_options %>
I assign the values of the array to the instance variable in the controller
def new
#time_options = Appointment.time_options
#doctor = Doctor.find(params[:doctor_id])
#appointment = #doctor.schedule.appointments.build
end
# GET /appointments/1/edit
def edit
#time_options = Appointment.time_options
#doctor = Doctor.find(params[:doctor_id])
#appointment = #doctor.appointments.find(params[:id])
end
# POST /appointments
# POST /appointments.json
def create
#time_options = Appointment.time_options
#doctor = Doctor.find(params[:doctor_id])
#appointment = #doctor.schedule.appointments.new(params[:appointment])
if #appointment.save
#send email
AppointmentMailer.appointment_confirmation(#appointment, I18n.locale).deliver
AppointmentMailer.new_appointment(#appointment, I18n.locale).deliver
redirect_to :action => 'thank_you'
else
render action: 'new'
end
end
And in the model I have defined a class method to build the array
def self.time_options
start_of_day = Time.zone.now.beginning_of_day
start_time = start_of_day + 9.hours
end_time = start_of_day + 17.hours
lunch_start = start_of_day + 13.hours
lunch_end = start_of_day + 14.hours + 30.minutes
times = []
until start_time > end_time
start_time = (start_time + 30.minutes)
unless start_time >= lunch_start && start_time < lunch_end
times << start_time
end
end
times.map{|t| [t.strftime("%I:%M%p").downcase, t.to_s(:db)] }
end
However when I submit the form, i get a undefined methodempty?' for nil:NilClass` error on:
<%= f.select :atime, #time_options %>
What I'm doing wrong?
This
<%= f.select :atime, #time_options %>
should be like this
<%= f.select :atime_id, #time_options %>
In the create method, start with the #doctor and go down the chain: schedule, then params[:appointment], until you find the nil, then figure out why it's nil. Rails.logger or pry if you're running rails s will be your friend.

Resources