using hashes to create a class - ruby-on-rails

when trying to create a class with a single argument, I am getting the following error: NameError: undefined local variable or method radius' for #<Circle:0x007fdcda2b75c8> from circle_constructor.rb:13:ininitialize'
class Circle
def initialize(circle_constructor = {})
circle_constructor = {#radius => radius, #diameter => diameter}
#radius = radius
#diameter = diameter
end
end

if i understand you correctly you try to initialize #radius and #diameter with the hash you got as a parameter so try the following:
class Circle
def initialize(circle_constructor = {})
## circle_constructor = {#radius => radius, #diameter => diameter}
## you are inserting wrongly values to local variable inside constractor wothout doing nothing with it so remove it or do this:
## #circle_constructor = { radius: radius, diameter: diameter }
## make sure you populate radius and diameter local variables before.
#radius = circle_constructor[:radius]
#diameter = circle_constructor[:diameter]
end
end

Ruby doesn't support this out of the box, but you can use Hashie library for this. It has several hash variants and dash would work well for this.
require 'hashie/dash'
class Circle < Hashie::Dash
property :radius, required: true
property :diameter, required: true
end
# USAGE
Circle.new(radius: 10, diameter: 5)
(On a side note, it's odd that your circle accepts both a radius and a diameter. Unless it's user input such as a quiz, you should be able to derive one from the other, so it would normally only have one constructor param and the other would be a method.)

Related

How do I set a default value for a parameter in Rails?

Controller
def index
markers = Marker.nearby(params[:lat], params[:lng], params[:radius])
end
Model
def self.nearby(lat, lng, radius)
approved.near([lat.to_f, lng.to_f], radius, units: :km)
end
Routes:
resources :markers
URL:
http://localhost:3000/markers?lat=11111111&lng=10101010101&radius=20
Notes:
In the URL below we have 3 paramaters(lat, lng and radius). and i want the radius value equal to 1 (1 km). so when the user open (http://localhost:3000/markers?lat=11.111111&lng=104.1010101) it'll get the default value with radius=1 (http://localhost:3000/markers?lat=11.111111&lng=104.1010101&radius=1).
I'd suggest setting the default value for radius in the model method. That ensures a consistent behavior even if you run it from the console or not using request parameters.
def self.nearby(lat, lng, radius)
approved.near([lat.to_f, lng.to_f], radius || 1, units: :km)
end
Then Marker.nearby(11.111, 104.010101, nil) should set radius value to 1. Please notice this will only work when radius is nil, will fail for empty strings. if that's a concern you should check for present? like:
def self.nearby(lat, lng, radius)
radius = radius.present? ? radius : 1
approved.near([lat.to_f, lng.to_f], radius, units: :km)
end
You can use fetch.
Marker.nearby(params[:lat], params[:lng], params.fetch(:radius, 1))

Geocoder and rails - wrong number of arguments (3 for 1)

I read all posts but don't find solution. I make a .near request with geocoder, and It work for one controller but doesn't work for another one with this error : Wrong number of arguments (3 for 1).
Here is the two same lines :
This one doesn't work in my school_controller.rb
#schools_premium = School.where(:subscription.exists => true)
#schools_aside = #schools_premium.near([params[:latitude], params[:longitude]], radius, units: :km).limit(3)
I try too with : #school.coordinates.reverse instead of params[:latitude] ..
But this one does (in home_controller.rb) :
#schools = School.near([params[:latitude], params[:longitude]], radius, units: :km).limit(30)
I have the geocoded_by and reverse_geocoder on my School model.
Does someone have the same issue ?
You can achieve by this way also:
#schools = School.near([params[:latitude], params[:longitude]], radius, units: :km).limit(30)
#schools_aside = #schools.premium_school
School.rb (model)
scope :premium_school, -> {where("subscription = ?", true)}

Undefined method for string

I don't understand why I can't call the method colorize from color.rb.
I wrote include color inside the class, but when I try to execute the script I get this error in wget:
undefined method `colorize' for #<String:0x00000001152d30>
This is the code:
$LOAD_PATH << './lib'
require 'color'
class Download
include color
def wget(arr)
FileUtils.cd('/mnt/list')
site = "xxxxx"
arr.each do |f|
wget = system("wget #{site}#{f}")
logger.info("wget: #{f}".colorize("blue"))
end
end
end
The file color.rb with the method colorize
module Color
def colorize(color, options = {})
background = options[:background] || options[:bg] || false
style = options[:style]
offsets = ["gray","red", "green", "yellow", "blue", "magenta", "cyan","white"]
styles = ["normal","bold","dark","italic","underline","xx","xx","underline","xx","strikethrough"]
start = background ? 40 : 30
color_code = start + (offsets.index(color) || 8)
style_code = styles.index(style) || 0
"\e[#{style_code};#{color_code}m#{self}\e[0m"
end
end
As soon as you want to call colorize method on Strings instance, you should monkeypatch the String class:
class String
include Color
end
include color string in your Download class is senseless.
The snippet might be put anywhere in your code, e. g. right after the Color module definition. Since you have String class monkeypatched as shown above, you yield an ability to call colorize on string instances. The summing up:
module Color
def colorize(color, options = {})
....
end
end
class String
include Color
end
puts 'a'.colorize(...) # ⇒ works

Validating parameters to create a class, parameters created in the controller arn't being added.

I create a class that takes two input parameters from the user, these input parameters are then used to create five others, the problem is that the five others don't show up when I check my validated paramaters only the first ones.
I know that all of the new parameters are added to the params but they don't show up in the model time_delta_params hash when I check what's in it only the first two. Thanks for any help!
My create method for the controller
def create
# XXX Add these columns to the model and populate them
# finalRating, positiveTweets, negativeTweets, neutralTweets, totalTweets
tweetRatings = {:finalRating => 0, :positiveTweets => 0, :negativeTweets => 0, :neutralTweets => 0}
#stock = Stock.find(params[:stock_id])
tweets = getTweets(#stock.hashtag, time_delta_params[:start], time_delta_params[:length].to_i)
tweets.each do |tweet|
case processTweet(tweet)
when 1
tweetRatings[:positiveTweets] += 1
tweetRatings[:finalRating] += 1
when -1
tweetRatings[:negativeTweets] += 1
tweetRatings[:finalRating] -= 1
else
tweetRatings[:neutralTweets] += 1
end
end
params[:final] = tweetRatings[:finalRating]
params[:positive] = tweetRatings[:positiveTweets]
params[:negative] = tweetRatings[:negativeTweets]
params[:neutral] = tweetRatings[:neutralTweets]
params[:total] = tweets.count
# printSomthingToRender(time_delta_params)
#time_delta = #stock.time_deltas.create(time_delta_params)
redirect_to stock_path(#stock)
end
My validation:
def time_delta_params
params.require(:time_delta).permit(
:start,
:length,
:final,
:positive,
:negative,
:neutral,
:total
)
end
You are not merging the additional parameters into the time_delta hash, but straight to the top level of params. time_delta is a hash within params.
You need to do something like:
params[:time_delta].merge!(final: tweetRatings[:finalRating],
positive: tweetRatings[:positiveTweets],
negative: tweetRatings[:negativeTweets],
neutral: tweetRatings[:neutralTweets],
total: tweets.count)
You're calling create with the time_delta_params that isn't going to contain the tweetRatings data. You would need to do something like params['time_delta'][:final] = tweetRating[:finalRating]. You could also call create and create your hash there or rename the values in the tweetRatings hash to match what is in the model.

RubyOnRails: Cannot convert a string to a float in my controller

I'm trying to make an active record that involves location. I get the longitude from the params, and try to use the Float() method to convert the locationLongitude and locationLatitude from a string to a float, and I get the following error:
undefined method `call' for #<Class:0x007ffead288530>
Here are the params that the method has access to:
{"locationName"=>"Stanford",
"locationLatitude"=>"37.42839679991957",
"locationLongitude"=>"-122.17553785073696"}
And this is the method in my controller that attempts to convert the strings into floats and make the query:
def local
radius = 10;
#sort = "local"
#locationName = params[:locationName]
#locationLongitude = Float(params[:locationLongitude])
#locationLatitude = Float(params[:locationLatitude])
#musings = Musing.(:longitude => (Float(#locationLongitude) - radius)..(Float(#locationLongitude) + radius))
end
Hope you can help. I also tried doing params[:locationName].to_f and that also didn't work.
Thanks, Paul.
I'd say it's better to move the processing from within your local method to the Musing (or other) model.
In your form - try to namespace your parameters such that it'd have a musing as an outer most one.
<input name='musing[locationName' ...>
In the controller
def local
# set some vars
#musings = Musing.search(params[:musing])
end
In the model
def self.search(params)
radius = 10
long = params[:locationLongitude]
lat = params[:locationLatitude]
return self unless long and lat
self.where(:latitude => lat.to_f-radius).where(:long => long.to_f-radius)
end
I can see you resolved the issue - but this might help
Please, change
params[:locationName].to_f
to
params[:locationName].to_s.to_f
The issue was in this line:
#musings = Musing.(:longitude => (Float(#locationLongitude) - radius)..(Float(#locationLongitude) + radius))
I wrote Musing.(...) instead of Musing.where(...)
What a scrub.

Resources