I have the method below and I get the error
"no implicit conversion of String into Integer"
on line
if (!thisitem['value'].to_i.match(/[\/-].{2}/).nil?)
A Little background: I am new to this project, this is a internal CMS. I am attempting to upgrade from Rails 2 to Rails 4. I come from a ASP.NET background.
Parameters: Parameters: {"utf8"=>"✓",
"authenticity_token"=>"ahD3oriEXY895BNx53nd03Q6PQZ1yOQkgkpCGM4OlVqXODjrl3EIb6Uqa9mqVwwWgCQhV5qxRebCmEyoP57HzQ==",
"info_items"=>{"1"=>{"id"=>"1", "description"=>"Billing Rate",
"value"=>"110"}, "2"=>{"id"=>"2", "description"=>"Travel Rate",
"value"=>"55"}}, "commit"=>"Update"}
def update_info
#updated_items=params[:info_items]
#updated_items.each do |thisitem|
#item=TrackInformation.find_by_id(thisitem)
if (!thisitem['value'].match(/[\/-].{2}/).nil?)
thisdate=thisitem['value']
if !thisdate.match(/\/.{2}/).nil?
newdate=Date.strptime(thisdate,"%m/%d/%Y")
else
newdate=Date.strptime(thisdate,"%m-%d-%Y")
end
thisdate=newdate
thisitem['value']=thisdate
end
#item.update_attributes(thisitem)
#item.changed_by=User.find(session[:user]).id
#item.save
end
end
edit:
so reading #Anand I realized that a date should not equal value because value is a dollar amount, so I modified the method to be:
def update_info
i = 1
#updated_items=params[:info_items]
#updated_items.each do |this_item|
#item=TrackInformation.find_by_id(this_item[i][:id])
#item.description = this_item[i][:description]
#item.value = this_item[i][:value]
#item.changed_by=session[:user].to_i
#item.save
i = i + 1
end
redirect_to :controller => 'admin', :action => 'list'
end
Now I get:
undefined method `[]' for nil:NilClass
Edit 2:
def update_info
byebug
#updated_items=params[:info_items]
#updated_items.each do |id, description, value|
#item=TrackInformation.find_by_id(id)
#item.value = value
#item.description = description
#item.changed_by=session[:user]
#item.save
end
redirect_to :controller => 'admin', :action => 'list'
end
this seems to work but puts this in the DB:
Edit 3:
def update_info
#updated_items=params[:info_items]
#updated_items.each do |this_item_key,this_item_value|
#item=TrackInformation.find_by_id(this_item_key)
#item.update_attribute(this_item_key, this_item_value)
#item.changed_by=session[:user]
#item.save
end
redirect_to :action => 'list'
end
Based on your params, each thisitem is a hash - you can get the key and value as block params, and use them appropriately. Also, if !(something).nil? can be simplified to if something.present?. Finally, it is a good idea to name variables with underscore - this_item instead of thisitem
Update: As the question has changed, updated the code below as well
def update_info
#updated_items=params[:info_items]
#updated_items.each do |this_item_key,this_item_value|
#item=TrackInformation.find_by_id(this_item_key)
#item.value = this_item_value['value']
#item.description = this_item_value['description']
#item.changed_by=session[:user]
#item.save
end
end
Related
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.
I am working on functionality whereby a table is displayed with records, each with radio buttons Reject and Approve. A user selects the appropriate radio button and presses process. Control is passed to process_campaigns. From here it breaks down the data and analyses each record's status. If it is approved it redirects to approve block and same with reject.
The following parameters are passed:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9TCExvCmDahAWGQloPdaRkSowbBaxZGwZnRa8sbNkWM=", "campaign"=>{"2"=>{"start_date"=>"2016-07-18 15:43:00", "end_date"=>"2016-10-15 12:20:00", "merchant_revenue"=>"10", "status"=>"Approved", "notes"=>""}, "1"=>{"start_date"=>"2016-07-15 12:20:00", "end_date"=>"", "merchant_revenue"=>"10", "status"=>"Approved", "notes"=>""}}, "Commit"=>"Process"}
def process_campaign
authorize! :operator, current_user.operator
params[:campaign].each do |key, value|
if value[:status] == "Approved"
redirect_to approve_operator_campaign_path(key), :id => key, :start_date => value[:start_date], :revenue_mode => value[:revenue_model], :end_date => value[:end_date], :active => true, :status => 307 and return
elsif value[:status] == "Rejected"
redirect_to reject_operator_campaign_path(key), campaign_name: key, notes: value[:notes], :status => 307 and return
end
end
redirect_to operator_campaigns_path, flash: { notice: "Campaigns have been processed."}
end
def reject
authorize! :operator, current_user.operator
params[:campaign].each do |key, value|
if value[:status] = "Rejected"
#campaign = Campaign.active.where(id: key, operator_id: current_user.operator_id).last!
#campaign.data.merge!({:notes=>value[:notes]})
#campaign.status = "Rejected"
#campaign.save(validate: false)
end
end
end
def approve
#campaign = Campaign.find(params[:id])
params[:campaign].each do |key, value|
if value[:status] = "Approved"
#applied_campaign = AppliedCampaign.new(:campaign_id => key, :start_date => value[:start_date]||Time.now, :end_date => value[:end_date], :active => true)
end
end
end
The problem is when control is passed to approve or reject the entire campaign string is passed with both records contained within whereas I want to seperate each record and pass it individually. Can anyone indicate why the entire campaign string is being passed?
Move the params inside the route helper
redirect_to approve_operator_campaign_path(key, param_1: 1, param_2: 2)
# Parameters: { "id"=>"2" "param_1"=>"1", "param_2"=>"2" }
Change your method to:
def process_campaign
authorize! :operator, current_user.operator
params[:campaign].each do |key, value|
if value[:status] == "Approved"
redirect_to approve_operator_campaign_path(key, id: key, start_date: value[:start_date], revenue_mode: value[:revenue_model], end_date: value[:end_date], active: true, status: 307) and return
elsif value[:status] == "Rejected"
redirect_to reject_operator_campaign_path(key, campaign_name: key, notes: value[:notes], status: 307) and return
end
end
redirect_to operator_campaigns_path, flash: { notice: "Campaigns have been processed."}
end
I get this error and for the life of me I can't figure out why. Help would be appreciated. :
error 3: error displayed after changes
error 4: after User.all.each do |user|
Error: Undefined method 'each' for nil: nilClass
my ruby/haml code is as follows
viewer code:
-# This file is app/views/projects/index.html.haml
%h1 All Project Tasks
= form_tag projects_path, :method => :get do
Include:
- #all_users.each do |user|
= user
= check_box_tag "users[#{user}]", 1, ("checked" if #filtered_users.find_index(user))
= submit_tag 'Refresh', :id => "users_submit"
%table#projects
%thead
%tr
%th{:class => ("hilite" if params[:sort] == "title")}= link_to "Title", {:controller => "projects", :sort => "title", :filter => #filtered_users.to_s}, :id => "title_header"
%th Task Details
%th Assigned Usertimot
%th{:class => ("hilite" if params[:sort] == "due_date")}= link_to "Due Date", {:controller => "projects", :sort => "due_date", :filter => #filtered_users.to_s}, :id => "due_date_header"
%tbody
- #projects.each do |project|
%tr
%td= project.title
%td= link_to "More about #{project.title}", project_path(project)
%td= project.user
%td= project.due_date.to_formatted_s(:long)
= link_to 'Add new project task', new_project_path
controller code:
class ProjectsController < ApplicationController
def show
id = params[:id] # retrieve project task ID from URI route
#project = Project.find(id) # look up project task by unique ID
# will render app/views/projects/show.<extension> by default
def index
#projects_users = Project.all_users
# remembered settings
if (params[:filter] == nil and params[:users] == nil and params[:sort] == nil and
(session[:filter] != nil or session[:users] != nil or session[:sort] != nil))
if (params[:filter] == nil and session[:filter] != nil)
params[:filter] = session[:filter]
end
if (params[:sort] == nil and session[:sort] != nil)
params[:sort] = session[:sort]
end
redirect_to projects_path(:filter => params[:filter], :sort => params[:sort], :users => params[:users])
else
if (params[:filter] != nil and params[:filter] != "[]")
#filtered_users = params[:filter].scan(/[\w-]+/)
session[:filter] = params[:filter]
else
#filtered_users = params[:users] ? params[:users].keys : []
session[:filter] = params[:users] ? params[:users].keys.to_s : nil
end
end
session[:sort] = params[:sort]
session[:users] = params[:users]
if (params[:sort] == "title")
if ( params[:users]or params[:filter] )
#projects = Project.find(:all, :order => "title")
end
end
if (params[:sort] == "due_date")
if ( params[:users]or params[:filter] )
#projects = Project.find(:all, :order => "due_date")
end
if (params[:sort] == nill)
if(params[:users] or params[:filter])
#projects = Project.all
end
end
end
end
def new
# default: render 'new' template
end
def create
#project = Project.create!(project_params)
flash[:notice] = "#{#project.title} was successfully created."
redirect_to projects_path
end
def edit
#project = Project.find params[:id]
end
def update
#project = Project.find params[:id]
#project.update_attributes!(project_params)
flash[:notice] = "#{#project.title} was successfully updated."
redirect_to project_path(#project)
end
def destroy
#project = Project.find(params[:id])
#project.destroy
flash[:notice] = "Project '#{#project.title}' deleted."
redirect_to projects_path
end
private
def project_params
params.require(:project).permit(:title, :description, :extended_description, :user, :due_date)
end
end
end
i understand that the spacing for haml may be a little off, just the nature of trying to format the code block thanks in advance!
viewer code:
class Project < ActiveRecord::Base
def self.all_users
allUsers = []
Project.all.each do |project|
if (allUsers.find_index(project.user) == nil)
allUsers.push(project.user)
end
end
return allUsers
end
end
You are probably getting the error on this line in your view:
#all_users.each do |user|
The reason for the error as I see it is that you don't have #all_users instantiated anywhere in your controller's index action method.
First switch #all_users to #projects_users. Also it appears that your all_users method in project.rb is overly complex and is returning nil. Try modifying project.rb to the following:
class Project < ActiveRecord::Base
def self.all_users
all.includes(:user).map(&:user).uniq
end
end
Undefined method 'each' for nil: nilClass
This error basically means you don't have any data in your variable.
In other languages, it would mean you've not delcared the variable. Because Ruby is object orientated, it will populate the variable with the nilClass class.
Many new Ruby devs are thrown by the "undefined method" exception message; it's the nilClass you have to look out for.
--
To explain the error properly, because Ruby is object orientated, every variable is actually a data object, represented by a class. In Rails, you can define these classes as models (User.find etc).
Unlike other languages, Ruby treats these objects as is -- it uses methods on them. Other languages fit data into functions, E.G PHP's each function:
#PHP
<$ each($people) $>
#Ruby
<% #people.each do |person| %>
Thus, the "no method" error basically means that Ruby cannot find the method you're calling on the nilClass. It throws developers because they think that "I have the x method on the User class", not realizing that the variable has been populated by the nilClass instead.
The short of it is that you have to either make your calls conditional, or populate the variable properly.
The error appears to be here:
#app/views/project/index.html.haml
#all_users.each do |user|
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def index
#projects_users = Project.all_users
end
end
You're not assigning #all_users at all
You're using an inefficient way to get "all users"
Here's what I'd do:
#app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def index
#users = Project.all_users
end
end
#app/models/project.rb
class Project < ActiveRecord::Base
scope :all_users, -> { joins(:users) } #-> this needs to be tested
end
#app/views/projects/index.haml
- #users.each do |user|
= user.name
I am pretty inexperienced with pure SQL, you'll be best referring to the joins documentation for a clearer perspective.
I have a form set up to take in date time value. This value will then be sent as a parameter into my controller method "bookingdate" where it will be compared with other dates in the bookings to ensure there is no double booking, using a do loop.
However when I submit the date form, rather than redirect to the next form where a user selects other details it throws me an error or redirects incorrectly.
Here is my controller
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
render :action => 'new'
end
Here is my routes
match '/bookdate', :to => 'bookings#bookingdate'
Add redirect_to helper and pass route to where progress
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
redirect_to path_where_you_want_to_redirect
end
I guess you want to perform some checks, if user has correct filled form
def bookingdate
#bookings = Booking.all
#bookings.each do |b|
if b.startdatetime == params[:startdatetime]
#musicians = Musician.where (["id != ?", b.musician_id])
end
end
if condition_successful
redirect_to path_where_you_want_to_redirect
else
render :bookingdate
end
end
I'm just beginning to (hopefully!) learn programming / ruby on rails and trying to push the results of a hash to an array using:
ApplicationController:
def css_class
css = Array.new
product = {#product.oil => ' oil', #product.pressure_meters => ' pressure_meters', #product.commercial => 'commercial'}
product.each do |key, value|
if key == true
css.push(value)
end
end
сss.join
end
And this in the ProductsController:
def create
#product = Product.new(params[:product])
#product.css_class = css_class
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render json: #product, status: :created, location: #product }
else
format.html { render action: "new" }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
This only seems to only save the last thing that was pushed to the array, I tried the below code on it's own and it seems to work, so I'm baffled as to where I'm going wrong?
def css_class
css = Array.new
product = {1 => ' pressure_meters', 2 => ' oil'}
product.each do |key, value|
if key > 0
css.push(value)
end
end
css.join
end
puts css_class
Thanks in advance.
In Ruby Hash can't have duplicate keys so
def css_class
css = Array.new
product = { #product.oil => ' oil',
#product.pressure_meters => ' pressure_meters',
#product.commercial => 'commercial' }
product.each do |key, value|
if key == true
css.push(value)
end
end
сss.join
end
will not work because
irb(main):0> h = { true => 'foo', true => 'bar', false=>'foo', false => 'bar' }
=> {true=>"bar", false=>"bar"}
your second example works only because you have distinct keys (1,2) so let's refactor your code a bit
def css_class
css = ""
product = { ' oil' => #product.oil,
' pressure_meters' => #product.pressure_meters,
' commercial' => #product.commercial }
product.each do |key, value|
css << key if value
end
сss.strip
end
it can be simplified even more however previous version should work fine too
def css_class
[ "oil ", "pressure_meters ", "commercial " ].inject(""){ |sum, val| sum += val if #product.send( val.strip ) }.strip
end
You can use Hash#values to get an array of your hash's values.
So:
product_values = product.values
And conditionally, you could pick the ones you want using select, like this:
product_values = product.select {|k,v| k == true }.values
Which is verbose for:
product_values = product.select {|k,v| k }.values
Thanks for pointing me in the right direction. I kept getting a 500 internal server error with your code Bohdan, not sure why, but played around with it and eventually found this to work:
def css_class
css = Array.new
product = { ' oil' => #product.oil,
' pressure_meters' => #product.pressure_meters,
' commercial' => #product.commercial }
product.each do |key, value|
css << key if value
end
css.join
end