Rails + Thinking-Sphinx polymorphic association - ruby-on-rails

class User < ActiveRecord::Base
has_many :followings, :as => :followable, :dependent => :destroy, :class_name => 'Follow'
has_many :follows, :as => :follower, :dependent => :destroy
define_index do
has follows.followable(:id), :as => :followable_id
has followings.follower(:id), :as => :follower_id
has follows.followable(:type), :as => :followable_type
has followings.follower(:type), :as => :follower_type
end
end
question: I can not search by type (always empty array). A bug? I would like to get all users where followers are of type 'AAA'.
User.search '', :with => { :follower_type => 'AAA' }
question: Why do I have to inverse my association to get the right result (index definition):
follows.followable(:id), :as => :followable_id
instead of
followings.followable(:id), :as => :followable_id
I would like to get a list of followers for a user with id=1
User.search :with => {:followable_id => 1} # List of followers for a user with id=1
Thx!

With regards to the first question - string filters don't work in Sphinx. This should change in the future (with Sphinx 1.10-beta, once Thinking Sphinx supports the new features), but not sure when that'll happen (I'd love to say soon, but can't promise anything).
There is a workaround available, though... but keep in mind you're handling an array of strings, so that's an additional level of complexity.
As for the second question, struggling to get my head around what the database is looking like (confusing names, but I'm lacking focus right now), so I'll just leave it at this for the moment.

Related

Rails 4.0.0 foreign key for models

Is this wrong to have that same foreign key for two different models? It's Rails 4.0.0 app so conditions are written like that. I ask because I got some problem with blinks and can't find it.
has_many :messages, :conditions => {:deleted => false, :subject_h => ''}
has_many :messages_send, :class_name => "Message", :foreign_key => "sender_id", :conditions => ['deleted_sender = ?', false]
has_many :blinks, :conditions => {:deleted => false, :subject_h => ''}
has_many :blinks_send, :class_name => "Blink", :foreign_key => "sender_id", :conditions => ['deleted_sender = ?', false]
I would do one of the two following things:
1 - Have one table per model (so one blinks table and one messages table).
2 - Use Single Table Inheritance (STI) for each messages. You would have only one table (senders in your case), with a type field that would differentiate between a blink and a message.
For simplicity here, I would personally go for the first option, and evolve to the STI later on if still needed.
The advantage would also be that you'll be able to declare your associations like this:
has_many :messages
has_many :blinks

Thinking Sphinx and multiple has_one

I've got multiple has_one associations in my model
class Invoice < ActiveRecord::Base
...
belongs_to :seller, :class_name => "Client", :foreign_key => "provider", :conditions => ['is_provider = ?', true]
belongs_to :customer, :class_name => "Client", :foreign_key => "receiver", :conditions => ['is_receiver = ?', true]
I'm trying to index it:
indexes [seller(:tbClientCode), seller(:tbClientLabel), seller(:tbClientName), seller(:tbClientNIP),
seller(:tbClientRegon), seller(:tbClientZip), seller(:tbClientCity), seller(:tbClientStreet),
seller(:tbClientHouseNr), seller(:tbClientHomeNr], :sortable => true, :as => :seller_fields
has [seller(:is_provider), seller(:is_receiver)], :sortable => true, :as => :seller_attributes
indexes [customer(:tbClientCode), customer(:tbClientLabel), customer(:tbClientName), customer(:tbClientNIP),
customer(:tbClientRegon), customer(:tbClientZip), customer(:tbClientCity), customer(:tbClientStreet),
customer(:tbClientHouseNr), customer(:tbClientHomeNr], :sortable => true), :as => :customer_fields
has [customer(:is_provider), customer(:is_receiver)], :sortable => true, :as => :customer_attributes
... and then some error occurs
ERROR: index 'invoice_core': sql_range_query: ERROR: column reference "is_receiver" is ambiguous
LINE 1: ...tomers_invoices"."id" = "invoices"."receiver" AND is_receive...
Changing syntax from customer(:tbClientName) to customer.tbClientName is not solution.
Some help would be greatly appreciated
Well, firstly: I don't think you actually want to combine all those columns into just one field and just one attribute?
So, remove the [] - you can pass in multiple columns, but if you pass in an explicit array, then that'll group those columns together into a single field/attribute. Thus, remove the :as option as well - you don't want all of those columns together having the same name, the generated SQL statement won't make any sense.
Secondly: attributes are sortable by their very nature, so you don't need to pass :sortable => true to the has call. Also: do you really need all of the fields to be sortable? Better to only mark the fields that should be sortable as such.
But lastly, and perhaps most importantly: the error that's actually happening is because of your conditions hash for your two associations. You're joining on the same table twice, but you don't have any table references in the conditions. Try changing both conditions settings to the following:
:conditions => {:is_provider => true}
:conditions => {:is_receiver => true}

extra has_many requirements

Assignment: title:string
Permission: user_id:integer, subject_class:string, subject_id:integer, action:string
Assignment has_many :permissions, :foreign_key => :subject_id
But how do I make sure that it knows about the subject_class == self.class.to_s requirement?
Update: Using :conditions => {:subject_class => 'Assignment'}, how can I ensure when I do permissions.new the :subject_class is also set.
This is something you want to use polymorphic associations for (http://wiki.rubyonrails.org/howtos/db-relationships/polymorphic)
In your Assignment model, you would do the following:
has_many :permissions, :as => :subject
And in your Permission model, you would do this:
belongs_to :subject, :polymorphic => true
However, you'll need to rename the subject_class field to subject_type in order for this to work implicitly. When all of this is done, you'll have everything you asked for for free from Rails. You won't need to pass :subject_type when you create a new Permission. You can create a Permission like this and :subject_type will be filled automatically for you:
assignment = Assignment.create(:title => "My Assignment")
permission = Permission.create(:subject => assignment, :action => "read", :user => current_user)
- or -
assignment.permission.create(:user => current_user, :action => "read")

Thinking Sphinx - Search filter not working

I installed Sphinx and Thinking Sphinx on ruby-on-rails 2.3.2 and on Windows 7 pc.
First of all, if I run rake ts:start, it won't start at all. It keep saying "Starting..." and it never starts. Even though, the simple search(with no filtering nor conditions) works fine. When I try to add a filter, it won't return any record.
My model looks like this:
class Announcement < ActiveRecord::Base
belongs_to :announcement_type
belongs_to :user
belongs_to :province
has_many :announcement_favorites
has_many :announcement_comments
has_many :announcement_subscriptions
has_many :announcement_views
acts_as_taggable_on :tags #,:category
validates_presence_of :title, :description, :expirationDate
define_index do
indexes title, :as => :title, :sortable => true
indexes description, :as => :description, :sortable => true
has province_id, :as => :province_id
end
And I'm searching this way:
Announcement.search params[:announcement][:search].to_s, :with => {:province_id => 1} ,:page => params[:page], :per_page => 10
Based on all the great documentation Thinking Sphinx has, and all the posts I've read about it, I can't understand what I'm doing wrong.
I just want to clarify that after I modify the index, I run the rake ts:index, ts:config commands and then I restart the searchd windows service just in case, and so the application, just to make sure everything is refreshed.
Thanks in advance,
Brian
I thought it was :conditions => {:province_id => 1} instead

Nested routing for models with double associations

In a toy Rails application, I'm modelling a situation where you have a number of pots, each containing an amount of something, and you can make transactions between the pots. A transaction can come from any pot, and go to any pot.
Here are the relevant parts of the models:
class Pot < ActiveRecord::Base
has_many :to_transactions, :foreign_key => "to_id", :class_name => "Transaction"
has_many :from_transactions, :foreign_key => "from_id", :class_name => "Transaction"
end
class Transaction < ActiveRecord::Base
belongs_to :to_pot, :class_name => "Pot", :foreign_key => "to_id"
belongs_to :from_pot, :class_name => "Pot", :foreign_key => "from_id"
end
This allows me to do the following at the console:
>> p = Pot.find(123)
>> p.from_transactions
=> # returns array of transactions from pot 123
>> t = p.to_transactions.new
=> # t is a new transaction with to_id set to 123
and so on.
I'm having a problem setting up the routing. For example, I would like:
/pots/123/from_transactions to give a list of all transactions from pot 123,
/pots/123/to_transactions/new to give the new transaction form, with the to_id set to 123
Is this possible? Any help gratefully received etc etc.
I would say a clean way of managing is that all the from_transactions related request go to from_transactions_controller and to_transactions related go to to_transactions_controller. But the underlying model could be same for both:
In routing file you could specify your routes as follows:
'pots/:id/to_transactions/new', :controller => 'to_transactions', :action => 'new'
'pots/:id/from_transactions/', :controller => 'from_transactions', :action => 'index'
Does that help?
My routes.rb now includes the following:
map.resources :transactions, :path_prefix => '/pots/:from_id', :as => :from_transactions
map.resources :transactions, :path_prefix => '/pots/:to_id', :as => :to_transactions
This means, for example, that a request to /pots/123/from_transactions/new is sent to the transactions controller, and params[:from_id] is set to 123.

Resources