Rails query where array attribute contains overlap with other array - ruby-on-rails

I have a model called Listing that represents a listing for an apartment sublet. These sublets can be rented out for different terms (summer, winter, etc). And so, the term for each sublet is stored as a serialized string. (I know this isn't the best way but i'm trying to get this app up) I am creating a filter function for these listings, so users can select what attributes they want in a listing and display the results that match the filter. I am having trouble, however, with the term part. Users can check off which terms they want the listing to be available for, and so this is stored in a serialized array as well. Using rails orm how can I do
listing=listing.where("term contains value(s) from input term")
basically I want this to return listings where the users preferred terms has atleast one overlap with the listings terms.
i.e. if a listing has terms of summer session 1 and winter and the user selects summer session 1 and spring, that listing should be returned.
Anyone have any ideas??

This is what you're looking for:
listings = Listing.where('term in (?)', terms)
or you can just do:
listings = Listing.where(:term => terms)

Related

Rails 4 - Ordering by something not stored in the database

I am using Rails 4. I have a Room model with hour_price day_price and week_price attributes.
On the index, users are able to enter different times and dates they would like to stay in a room. Based on these values, I have a helper method that then calculates the total price it would cost them using the price attributes mentioned above.
My question is what is the best way to sort through the rooms and order them least to greatest (in terms of price). Having a hard time figuring out the best way to do this, especially when considering the price value is calculated by a helper and isn't stored in the database.
You could load all of them and do an array sort as is suggested here, and here. Though that would not scale well, but if you've already filtered by the rooms that are available this might be sufficient.
You might be able to push it back to the database by building a custom sql order by.
Rooms.order("(#{days} * day_price) asc")

Rails Search One Column On Multiple Saved Terms (Saved Searches In Model)

One table, one column ('headline' in an RSS feed reader). On the front end, I want a text area in which I can enter a comma-separated list of search terms, some multi-word, like for 'politics':
rajoy, pp, "popular party", "socialist party", etc
This could either be stored as part of a separate search model or as a keyword column on the 'category' or 'story' models, so they can be edited and improved with different terms from the front end, as a story develops.
In the RSS reader, have a series of links, one for each story or category, that, on being clicked return the headlines that contain one (or more) of the search terms from the stored list.
In a later version, it would be good to find headlines containing several of the terms in the list, but let's start simple.
Have been doing lots of reading about postgres, rails, different types of searches and queries, but can't seem to find what I want, which I understand is basically "search 'headlines' column against this list of search terms".
Sounds like it might be an array thing that's more to do with controllers in Rails than postgres, or cycling through a giant OR query with some multi-word terms, but I'm not sure.
Does anyone have any better pointers about how to start?
Users
If this will be user specific, I would start with a User model that is responsible for persisting each unique set of search terms. Think logon or session.
Assuming you use the Category method mentioned before, and assuming there's a column called name. Each search term would be stored as a separate instance in the database. Think tags.
headlines that contain one (or more) of the search terms from the stored list
Categories
Since each Category has many terms, and all the queries are going to be OR queries, a model that joins the User and Category, storing a search term would be appropriate.
I'm also assuming you have a Story model that contains the actual stories, although this may not be persisted in the database. I'm predicting your story model has a heading and a body.
Terminal Console
rails generage model SearchTerm query:string user:references category:references && rake db:migrate
Models
On your existing User and Category models you would add:
# app/models/user.rb
has_many :search_terms
has_many categories, through: :search_terms
# app/models/category.rb
has_many :search_terms
has_many :stories
Rails Console
This will automatically make it possible for you to do this:
#user = User.last # this is in the console, just to demonstrate
#category = Category.find_by_name("politics")
#user.search_terms.create {query: "rajoy", category: #category}
#user.search_terms.create {query: "pp", category: #category}
#user.search_terms.where(category_id: #category.id).pluck(:query)
-> ['rajoy', 'pp']
Controllers
What you will want to do with your controller (probably the Category controller) is to parse your text field and update the search terms in the database. If you want to require commas and spaces to separate fields, you could do:
#user.search_terms.where(category: #category).delete_all
params[:search_term][:query].split(", ").map{|x| x.gsub("\"", "")}.each do |term|
#user.search_terms.create({category: #category, query: term})
end
Front End
Personally though, I'd make the front end a bit less complicated to use, like either just require commas, no quotes, or just require spaces and quotes.
Search
For the grand finale, for the Stories to be displayed that have search terms in their heading:
Story.where(#user.search_terms.where(category: #category).pluck(:query).map { |term| "heading like '%#{term}%'" }.join(" OR "))
I would recommend using pg_search gem rather than trying to maintain complicated queries like this.
Note: I'm sure there are errors in this, since I wasn't able to actually create the entire app to answer your questions. I hope this helps you get started with what you actually need to do. I encourage you as you work through this to post questions that have some code.
References
Rails guides: choosing habtm or has many through
gem 'pg_search'
Stack Overflow: Search a database based on query

Autocomplete Vs Pagination

I have a Rails Model with a relatively small number of entries (Currently at ~ 300 and will probably never go past 1000).
It currently paginates items on its index page to show 20 results a page.
I have just added Twitter Typeahead to the search field, and I'm using the record's names to supply the autocomplete suggestions. The problem is that as I'm paginating the results, I'm only able to offer suggestions for the 20 items from the current paginated batch.
The only thing I need from each model is its name, and I don't want to load/parse every record as this will undo most of the advantages from pagination.
So how can I retain sensible pagination, but also access the names of all records in an efficient manner?
You could fetch the names separately with pluck.
#names = MyModel.pluck(:name)
Note that in Rails 3 you can only provide 1 column name as argument for pluck.
Pagination usually resorts to LIMIT, so the only way to still retrieve all records, is to do another query.
With pluck you're only retrieving the field that you want from the database, and you won't have the overhead that ActiveRecord brings when you would go through a complete collection of all your models.

Create a table with first seen pages by user instead cookies. Is a bad practice?

I'm trying to avoid client side cookies because of different browsers to show again tour around pages in my app.
The user only have to see the tour when he firsts saw it. Then I'm thinking in a table like this:
table: users x pages_that_viewed
user_id seen_page seen_profile seen_another_page...
12 2012-12-12
13 2012-12-12 2012-12-12
Then I will have to join the table users with this one every time...
Another solution then will be adding this columns directly to users table.
Depending on how many pages you have and how many pages you are planning on adding, each additional page will require a database schema modification. Generally speaking, it's not a good idea. You can create one record per user per page instead. Index on user_id, page_id. If you want to know when they accessed it, third field would be date, otherwise a boolean will do. Another alternative is to use bitmap, but that will not work if you need dates, however it will only take 1 record per page to keep track of all user visits.
Bitmap field would store something like this 001000100011110010 where each digit represents a user_id and stores a visit to that page. Ex. user_id 12, would be the 12th digit 0 or 1 etc. On a visit you would update 1 field and set Nth digit to 1. Bitmaps are generally very fast and support some additional operations like unions, intersections etc.
I think a column would be more cost effective, much less queries...
try a boolean tour column then when someone logs to your app just fetch the column and store it in a session
session[:tour] ||= #user.tour
after reading your last comment i came up with this idea, I think you should make a relation between users and pages that would be a many to many asociation, then you could have a junction table pages_users with columns user_id and page_id, then at each render check if the current user has the current page. i think that is the best way to go.

Returning Search Results in Rails

I am having a problem implementing a special kind of search for my Rails application. I am working on an achievement system where you can search for a set of users in a search form (e.g., the query being "Ross, Adam, Jake") and it returns all of the common achievements that the users have unlocked (e.g., if users Ross, Adam, and Jake all had an achievement named "You are winner!"). I have three tables, one for achievements, one for users, and a join table. We have tested the associations and such, so we know that works.
My first idea was to put the search terms in an array and get the search results for each item in the array and place them into respective "search result arrays". Then, I was thinking to go through each item in search result array 1 to see if it appears in both of the other result arrays. The objects that appear in all three of the search result arrays would be returned and displayed on a page.
Is there an easy way to implement this without writing a bunch of my own code? Are there some functions I should know about? Any help will be appreciated!
Well, both Ransack and it's predecessor (MetaSearch) are useful gems for creating complex search forms.
In general I think you want to do something like select distinct achievement ids for user ids in an array. Off the top of my head I'm not quite sure how you should write it... others may know.
Look at the documentation on MetaSearch (more established) and see if you see a pattern that fits, if not check Ransack (more advanced).
You can use some autocomplete plugin for user names and convert the names to ids on the fly, that way you won't have to deal with converting user names to ids in backend later.
For common achievements, if a user can have a achievement only once, aggregating the results in join table and counting the results with achievement ids would be the way to go.
You can provide more details for a more detailed answer. :)
You can use Sunspot which is allows easy solr integration with Ruby and Rails

Resources