Thinking sphinx geosearch issues - ruby-on-rails

I need to search locations with sort by distance from passed coordinates.
app/indices/location_index.rb
ThinkingSphinx::Index.define :location, :with => :active_record do
indexes :name
has latitude, longitude
end
Try to search:
> Location.search(:geo => [53.348962, 83.777988], :order => "#geodist DESC").size
ThinkingSphinx::SyntaxError: sphinxql: syntax error, unexpected USERVAR, expecting IDENT (or 5 other tokens) near '#geodist DESC LIMIT 0, 20; SHOW META'
> Location.search(:geo => [53.348962, 83.777988],:with => {"#geodist" => 0.0..5000.0}, :order => "#geodist DESC").size
ThinkingSphinx::SphinxError: sphinxql: only >=, <=, and BETWEEN floating-point filter types are supported in this version near '#geodist BETWEEN 0.0 AND 5000.0 AND sphinx_deleted = 0 ORDER BY #geodist DESC LIMIT 0, 20; SHOW META'
Sphinx 2.0.6-release (r3473; Oct 22, 2012)
thinking-sphinx (3.0.1)
Update:
Pat Allan suggested:
Geodist no longer requires the # symbol - so try the following instead:
Location.search(:geo => [53.348962, 83.777988], :order => "geodist DESC").size
Location.search(:geo => [53.348962, 83.777988],:with => {:geodist => 0.0..5000.0}, :order => "geodist DESC").size

Just in case people find this question thought I'd add the answer in the correct format and with a little more explanation.
Versions of Sphinx prior to 2.1.1 made the calculated distance available via the #geodist internal variable. In versions of Thinking Sphinx compatible with newer versions of Sphinx the value of GEODIST() has been aliased to geodist.
So this:
Location.search(:geo => [53.348962, 83.777988], :order => "#geodist DESC").size
Becomes:
Location.search(:geo => [53.348962, 83.777988], :order => "geodist DESC").size
It's also worth pointing out in this example that the coordinates being supplied in the above example are in the incorrect format. They're in degrees rather than radians: http://pat.github.io/thinking-sphinx/geosearching.html. To transform them you can do:
def degrees_to_radians(degrees)
degrees * Math::PI / 180
end
Hope that helps!

Related

How do I access "request" and "session" objects from within my rspec tests?

I have a Rails 4.2 application that does different business depending on host name. I know this practice is frowned upon in certain circles but I managed to get the same code base working on about 400 websites, the amount of time|cpu|ram|db|money|squirrels saved is tremendous.
Eg:
For www.example.com for user john#doe.com it might show Product 1 with a $5000 price tag;
For www.blah.com for all usrs it might show Product 1 with a $123 price tag. And a shipping fee of $400.
This is all based on host name and a number of variables stored into session when users visit and/or log in to the website.
I'd like to write a bunch of specs to test various aspects of the application but I need to be able to set the request.host, format and some things in the session.
How do I get this done?
Later edit:
I managed to do a find and replace through the source code and get the session/request access done from within some helper methods. Now I can stub within my specs as follows:
allow_any_instance_of(ApplicationHelper).to receive(:detect_user_info_by_ip).with("ip").and_return( { :provider => "dummy", :ip => "127.0.0.1", :lat => 1.0, :latitude => 1.0, :lon => 2.1, :long => 2.1, :longitude => 2.1, :regi
on => "EU", :country => "GB", :city => "Testville", :country_iso2 => "GB", :success => true} )
allow_any_instance_of(ApplicationHelper).to receive(:detect_user_info_by_ip).and_return( { :provider => "dummy", :ip => "127.0.0.1", :lat => 1.0, :latitude => 1.0, :lon => 2.1, :long => 2.1, :longitude => 2.1, :region => "EU",
:country => "GB", :city => "Testville", :country_iso2 => "GB", :success => true} )
Bottom line is: easier to refactor and stub than access the request and session objects from within specs.

Changing the currency format for product prices within Spree

I'm upgrading spree to from spree 1.0 to 1.3 and get stuck with the new currency options.
I want to render prices as: '€ 100' but instead get '€100'. How do I get a space between the unit and the value?
Note: Changing the locale file doesn't work, since it uses the money gem.
There are a bunch of ways to do this. The easiest would probably be to re-register the Euro currency with a different symbol.
Put the following in an initializer:
# encoding: utf-8
Money::Currency.register({
:priority => 1,
:iso_code => "EUR",
:iso_numeric => "978",
:name => "Euro",
:symbol => "€ ",
:subunit => "Cent",
:subunit_to_unit => 100,
:separator => ".",
:delimiter => ","
})
A rails console now reports:
> Spree::Money.new(100, currency: 'EUR')
=> € 100.00
I did the following in my config/initializers/spree.rb to inject a different symbol:
Money::Currency.table[:chf].merge!(symbol: 'CHF ')
This way the currencies aren't going to mix up.
Thanks a lot.
In my case, used the following to change the symbol generated by the to_html method, in case anyone has the same problem.
# encoding: utf-8
Money::Currency.register({
:priority => 1,
:iso_code => "CLP",
:iso_numeric => "152",
:name => "Chilean Peso",
:symbol => "$",
:subunit => "Peso",
:subunit_to_unit => 1,
:separator => ",",
:delimiter => ".",
html_entity: "$"
})
I solved the problem with the following in an initializer, e.g. config/initializers/currency_formatting.rb:
# Display prices with a space between symbol and number:
Spree::Money.default_formatting_rules[:symbol_before_without_space] = false
This hooks into the formatting rules found in Spree::Money, which can control all the formatting Options of the Money Gem, including the one placing a space between the symbol and the number. This has the advantage over the other solutions presented here that it works with all currencies at once.
Okay, this was pretty easy. As of gem version money(6.16.0).
In Spree intializer spree.rb Recommended way:
Spree.config do |config|
...
...
# Below is deprecated
Spree::Money.default_formatting_rules[:symbol_before_without_space] = false
# Instead try this
Spree::Money.default_formatting_rules[:format] = '%u %n'
end

HBase via MassiveRecord in Ruby is causing an abort

When using MassiveRecord over thrift to save a record into HBase, I get a strange "abort" error.
Here is some code that will reproduce the error on Mac OS X, with hbase (0.92.0 and 0.94.0) install via homebrew.
require 'massive_record'
MassiveRecord::ORM::Base.connection_configuration = { :host => 'hbase' }
class Woot < MassiveRecord::ORM::Table
default_scope select(:data)
column_family :data do
field :name, :string
end
end
woot = Woot.new( :name => 'rawr' )
woot.save
This always causes the process to halt, leaving the message
[1] 8756 abort ruby massive_woot.rb
Retrieving works just fine, but I can't seem to save the records.
Here is what the schema looks like:
>> describe 'woots'
DESCRIPTION ENABLED
{NAME => 'woots', FAMILIES => [{NAME => 'data', BLOOMFILTER => 'NONE', REPLICATION_SCOPE => '0', VERSIONS => '3', C true
OMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCA
CHE => 'true'}]}
1 row(s) in 0.0190 seconds
This turned out to be a versioning issue. MassiveRecord v0.2.2 depends on thrift 0.6.0 (specified by an "= 0.6.0" version in the Gemfile).
I solved this for now by pulling off the "develop" branch of MassiveRecord from github.

Mongoid 3 bulk updates

Bulk updates are no longer working after upgrading to Mongoid 3. In Mongoid 2, I had the following:
Shift.where(
:account_id => current_account.id,
:location => self.department.location.name,
:department => self.department.name,
:position => self.name_was,
:color => self.color_was,
:date.gte => Date.current
).update_all(position: self.name, color: self.color)
I know the criteria is returning results but it no longer updates the documents. Here's the statement in Mongoid 3:
Shift.where(
:account_id => current_account.id,
:location => self.department.location.name,
:department => self.department.name,
:position => self.name_was,
:color => self.color_was,
:date.gte => Date.current
).update(position: self.name, color: self.color)
I'm running Rails 3.2.7 and Mongoid 3.0.3. Has anything changed that I'm not aware of? Also here's the entry from the logs:
MOPED: 127.0.0.1:27017 UPDATE database=development collection=shifts selector={"$query"=>{"account_id"=>"5017e8774f4e481fe3000001", "location"=>"Downtown", "department"=>"Cashes", "position"=>"Cash 1", "date"=>{"$gte"=>2012-08-01 00:00:00 UTC}}, "$orderby"=>{"start_at"=>1}} update={"$set"=>{:position=>"Cash A", :color=>"#42ed23"}} flags=[:multi] (0.2141ms)
However, nothing gets updated in the database.
I think it's because your query use a String like account_id, not a Moped::BSON::ObjectId.
If you do the where without the update. You have no result I supposed.

Ruby add_item for eBay

I am attempting to write a ruby on rails app that posts an item to eBay. Cody Fauser/Garry Tan have a gem called ebayApi which is built on top of the ebay gem. When I attempt to post an item, I am getting an error back from ebay that says the condition ID is required for this category. I have found a category that does not require the condition, and I can post to that category. Searching through the eBay API documentation, I have found a tag conditionID under the "item" class. However, in the documentation for ebayAPI, there is no such tag. Looking back at the ebay API documentation, there is an older way to specify condition, using lookup_attributes. I have noted that the return xml is coming in API version 745, and Garry Gan's updated of the ruby interface is running version 609. I have tried using the lookup, and seem to get the same error (condition required). I am using the following code to specify the item:
#ebay = Ebay::Api.new :auth_token => #seller.ebay_token
item = Ebay::Types::Item.new( :primary_category => Ebay::Types::Category.new(:category_id => #ebayTemplate.categoryID),
:title => #ebayTemplate.name,
:description => #ebayTemplate.description,
:location => #ebayTemplate.location,
:start_price => Money.new((#ebayTemplate.startPrice*100).to_d, #ebayTemplate.currency),
:quantity => 1,
:listing_duration => #ebayTemplate.listingDuration,
:country => #ebayTemplate.country,
:currency => #ebayTemplate.currency,
:payment_methods => ['VisaMC', 'PayPal'],
:paypal_email_address => '********#gmail.com',
:dispatch_time_max => 3,
:lookup_attributes => [Ebay::Types::LookupAttribute.new( :name => "Condition", :value => "New")],
# :attribute_sets => [
# Ebay::Types::AttributeSet.new(
# :attribute_set_id => 2919,
# :attributes => [
# Ebay::Types::Attribute.new(
# :attribute_id => 10244,
# :values => [ Ebay::Types::Val.new(:value_id => 10425) ]
# )
# ]
# )
# ],
:shipping_details => Ebay::Types::ShippingDetails.new(
:shipping_service_options => [
# ShippingServiceOptions.new(
# :shipping_service_priority => 2, # Display priority in the listing
# :shipping_service => 'UPSNextDay',
# :shipping_service_cost => Money.new(1000, 'USD'),
# :shipping_surcharge => Money.new(299, 'USD')
# ),
Ebay::Types::ShippingServiceOptions.new(
:shipping_service_priority => 1, # Display priority in the listing
:shipping_service => #ebayTemplate.shipSvc,
:shipping_service_cost => Money.new((#ebayTemplate.shipSvcCost*100).to_d, #ebayTemplate.currency),
:shipping_surcharge => Money.new((#ebayTemplate.shipSurcharge*100).to_d, #ebayTemplate.currency)
)
],
:international_shipping_service_options => [
Ebay::Types::InternationalShippingServiceOptions.new(
:shipping_service => 'USPSPriorityMailInternational',
:shipping_service_cost => Money.new((#ebayTemplate.shipSvcCost*100).to_d, #ebayTemplate.currency),
:shipping_service_priority => 2,
:ship_to_location => #ebayTemplate.shipToLocation
)
]
),
:return_policy => Ebay::Types::ReturnPolicy.new (
:description => 'this product for suckers only!',
:returns_accepted_option => 'ReturnsAccepted'
)
#:condition_id => 1000
)
#response = #ebay.add_item(:item => item)
As you can see, it is just a mutation of the example given by Cody Fauser. The condition_id at the bottom will bring up an error as there is no such attribute. It seems to me there is no facility for this in the gem since the requirement came into existence after the gem was created. I have not been able to find any other gems to connect with ebay. I have also noticed, there are very little complaints about this even though people are still downloading the gem (10 people downloaded it today). I think there are quite a number of people writing for ebay. Is there a key word I am missing to specify the condition? A work around that people have been using? Another gem I have missed?
There is an existing item_conditions_codes.rb in the gem's type directory and only has two values New and Used. Guess you could add more values in there. However still needs mapping to ID's per the updating (and changed from Attributes) method
You have to modify in the gem library in .. ruby/1.8/gems/ebayapi-0.12.0/lib/ebay/types/item.rb
and add the following new lines
# added to allow ConditionID to be pushed into XML
numeric_node :condition_id, 'ConditionID', :optional => true
then in your ruby ebay code use the following convention
:condition_id => 1500,
At least that seems to work for me right now.

Resources