How to show unique strings in Rails? - ruby-on-rails

I want to categorise Companies by letters in my listing page.
But there are multiple records that start with the same letter. I can get the first letters of Company names with the .first method.
But my code shows duplicate letters.
Controller:
#brand = Brand.where(slug: params[:brand]).first
#companies = Company.where(brand_id: #brand.id)....
View:
<% #companies.each do |c| %>
<li>
<%= link_to company_path(c.brand.name,c.id) do %>
<%= c.name.first %>
<% end %>
</li>
<% end %>
How would I show only unique letters?

New code (with some changes, assuming company belongs_to brand and brand has_many companies)
#brand = Brand.where(slug: params[:brand]).first
#companies = #brand.companies
##list is a hash with letters as keys and an array of companies starting with this letter
#list = Hash.new { |h,k| h[k]=[] }
#companies.each { |comp| #list[comp.name[0]] << comp }
#As “engineersmnky” suggested on a comment the last two sentences can be simplified:
#list = #companies.group_by { |c| c.name[0] }
View:
<% #list.each do |letter, companies| %>
<h2><%= letter %><h2>
<% companies.each do |c| %>
<li>
<%= link_to c.name, c %>
</li>
<% end %>
<% end %>

You're iterating through all companies so if you have companies like, Facebook and Foxtel, a link with F tag is going to be duplicated. You can do something like
categories = #companies.where(brand_id: #brand.id).pluck(:name).map(&:first).uniq
In the above code all it is doing is getting a list of company names and extracting out the first letter and removing the duplicates.
Now you can iterate through the categories and create a link for the category and inside the category page you can get companies starting from that letter
Company.where('name LIKE ?', "%#{starting_character}%")
starting_character gets sent from the list of categories page.

Related

Ruby array only storing last value, not all values

I have a Ruby app with Products and Categories.
I would like to have a category index page that displays 1 product photo for each category.
Right now, it shows the last product photo for all categories. (So, with 16 categories, it shows the product photo for category 16 on every category.)
I think I need to fix how I store or call the Products array. How do I do that?
Code --
in categories_controller.rb
def index
#categories = Category.all.order('name ASC')
#products = []
#categories.each do |category|
#products = Product.where(category_id: category.id).take(1)
end
end
in categories/index.html.erb
<% #categories.each do |category| %>
<% #products.each do |product| %>
<%= link_to image_tag(product.image), category %>
<% end %>
<%= link_to category.name, category %>
<%= category.description %>
In your index action, change the line:
#products = Product.where(category_id: category.id).take(1)
To:
#products << Product.where(category_id: category.id).take(1)
UPDATE:
Since take(1) will return an object in array, you need to simply change it to:
#products << Product.where(category_id: category.id).take

Rails - Unique Array in View

Having a Bit of trouble displaying unique results from my database. I have a database called "Activities". Each Activity has an associated Sport through sport_id. There may be many activities with the same sport_id.
I want to display a list of all sports linked to the activities database without displaying (for example "Football") twice.
FYI : Venues have many Facilities and Facilities have many Activities.
Controller:
#sports = Sport.all
#activities = Activity.paginate(page: params[:page])
#facilities = Facility.where(venue_id: #venue.id)
View:
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").each do |a| %>
<li><%= Sport.find(a.sport_id).name %>, (<%= a.facility_id %>)</li>
<% end %>
<% end %>
This shows:
Football, (2)
Hockey, (2)
Hockey, (2)
Football, (5)
I would like to display just:
Football
Hockey
Any ideas?
A simple solution would be to reduce your array with ruby in the view using: uniq!
<% #facilities.each do |f| %>
<% #activities.find(:all, :conditions => "facility_id == #{f.id} ").uniq! { |a| a.sport_id }.each do |a| %>
<li><%= link_to Sport.find(a.sport_id).name, Sport.find(a.sport_id) %></li>
<% end %>
<% end %>
Another way may be to perform a single query on your DB since Sport what you want to narrow down
In controller:
#sports = Sport.joins(activities: [facility: :venue]).where(facilities: { venue_id: #venue.id }).distinct
In view:
<% #sports.each do |sport| %>
<li><%= link_to sport.name, sport %></li>
<% end %>
I am not sure about your DB schema so I went with what I thought you would have done, but it might needs some tweakings.
I hope I helped you.
try to use reject before each
<% #facilities.reject{your condition here}.each do |f| %>

Ruby on Rails: Grouping search results by category

I am working on a RoR WebApp. I'm trying to group results on the search page based on their taxonomy. What I want to do is to show a header for a category and list all results under that category. Something like:
CAT 1
products
CAT2
products
CAT3
.
.
I am trying using the following code:
<% if products.any? %> #products is the list of search results
<%= render :partial=> 'product_listing_feature', :locals => {:scope => scope, :scope_type => scope_type} %>
<div id="ql_product"></div>
<div class="product_rows">
<%taxons.each do |taxon|%> # taxons contains the list of unique categories in products
<div class = "product_row">
<h1><%=taxon%></h1>
<% taxonProducts = Array.new %>
<% products.each do |product| %>
<%#ptaxon = product.get_taxonomy%>
<%if #ptaxon == taxon%>
<% taxonProducts.push(product) %>
<% end %>
<% end %>
<div class ="featured_product_list">
<ul class = "featured_products">
<div class = "page">
<%= render :partial=> 'product_listing', :locals=>{:collection=> taxonProducts} %>
</div>
</ul>
</div>
</div>
<% end %>
</div>
<% end %>
Surprisingly it starts the 2nd category from a new row, but the following categories appeared jumbled up, something like
CAT1
products
CAT2
products CAT3
products
picture would give a better idea.
I am really surprised why it works only for one iteration. Could someone please help me fix this.
Thanks a lot
Way, way too much logic for a view. Just use group_by in your controller, which will give you a mapping of names to arrays of products:
products = Product.includes(:taxon).group_by { |p| p.taxon.name }

grouping children by parent attribute

Here's what I am trying to achieve:
Group_x.name
member1.name -- member1.join_date -- etc
member2.name -- member2.join_date -- etc
...
Group_y.name
member1.name -- member1.join_date -- etc
member2.name -- member2.join_date -- etc
...
What I'm going for is really very similar to this although the implementation there doesn't work for me.
I've gotten this far in my controller:
def index
# https://stackoverflow.com/a/17835000/2128691
#user_group_ids = current_user.student_groups.map(&:id)
#students = Student.where('student_group_id IN (?)', #user_group_ids)
# https://stackoverflow.com/a/10083791/2128691
#students_by_group = #students.uniq {|s| s.student_group_id}
#title = "All students"
end
and calling the following in my view -
<% #students_by_group.all.each do |x| %>
<p>
<%= "#{x}" %>
</p>
<% end %>
gives me a list of all student objects. if i call <%= "#{x.name}" %> or <%= "#{x.created_at}" %>, etc, I get the correct information, and everything is great.
But now that I have all this information, how can I put the group.name (in my code it would be x.student_group.name) as a header for all of the students for which that group_name is true?
I think you need to use group_by on #students_by_group like this:
#students_by_group = #students_by_group.group_by { |s| s.student_group }
This would return a hash with the keys being the student group objects and the values being the students that belongs to this group, then you can do this in your view:
<% #students_by_group.each do |group, students| %>
<h3><%= group.name %></h3>
<% students.each do |x| %>
<p>
<%= "#{x}" %>
</p>
<% end %>
<% end %>
As an additional note, the group_by would fire a query for each student, so you may want to eagerly load the student group for each student like this for some performance gain:
#students = Student.where('student_group_id IN (?)', #user_group_ids).includes(:student_group)

rails where condition works in console, but not in web server

I am new in RoR.
The problem is, I created fully functional product categorization with Ancesrty. But now I want to be able to retrieve products that is under these subcategories.
This is my categories show controller
#category = Category.find(params[:id])
Here is categories#show view.
<b>Name of the category:</b>
<%= #category.name %>
<div class="product"
</div>
</p>
<% unless #category.children.empty? %>
<ul id="sub-menu">
<% #category.children.each do |sub1| %>
<%= link_to (sub1.name), sub1 %>
<%end%>
<%end%>
It all works fine. but now I want to add in view categories/show function that shows all products that is under that category.
I added such code.
In category/show controller
#cat_id = #category.id
#product = Product.where("category_id = ?",#cat_id)
In the categories show view I added
<td><%= #product.name %></td>
Then clicking on some subcategory where should appear few products, there just shows up Product
To check if the code is right I put in the console. There it works fine and retrieve products related to this category.
I dont understand why then code not working in webserver when I launch application ?
Could it be because of some erorr in Associations ?
Thanks !
in your controller, a more readable way is to use the plural form to indicate that you are expecting more than 1 object
#products = Product.where("category_id = ?", #cat_id)
Then in the view, just loop through these products
<% #products.each do |product| %>
<%= product.name %>
<% end %>
#product = Product.where("category_id = ?",#cat_id)
will return an array if there are any products. So you will need to loop through the array.
<% #product.each do |product| %>
<%= product.name %>
<% end %>
I accept both of the answers, But I want to suggest to use Active Record Association for this type of problems. This makes your solution easier.
If you want to fetch only one product, you can use the find_by_ helper method of the model:
#product = Product.find_by_category_id(#cat_id)
With this it will fetch the first matching product which has category_id equal to #cat_id.
If you want to fetch all the products which belong to a category, you need to fetch all the products as others suggested:
#products = Product.where(:category_id => #cat_id)
And then in the view:
<% #products.each do |product| %>
<%= product.name %>
<% end -%>

Resources