How to group collection by columns with rails - ruby-on-rails-3

My table named stocks contains product_id, color_id, storage_id and in_stock as columns.
For a given product I want to group all stocks by storage, then for each storage I want to show product (color): in_stock
How should I write a method and how to render?

<% Stock.all.group_by(&:storage).each do |storage, products| %>
Storage: <%= storage %>
<% products.each do |product| %>
(<%= product.color_id %>): <%= product.in_stock %>
<% end %>
<% end %>
Edit: updated to use ERB, and in_stock as a number and not a boolean yes/no column, and use color_id in place of color.name because that assumes you have a relationship to a color.

Not structured exactly how you need it (not enough info from your post), but something like this perhaps?
items = Stock.select('color_id, in_stock').group('stocks.storage_id').where(:product_id => foo)
items.each {|item| puts "(#{lookup_color(item.color_id)}): #{in_stock}"

Related

Query model for all possible values of a column - Ruby Rails [duplicate]

How can I get unique values from column in the table?
For example, I have this Products table:
ID NAME CATEGORY
1 name1 1st_cat
2 name2 2nd_cat
3 name3 1st_cat
Here I want to get only 2 values - 1st_cat and 2nd_cat:
<%Products.each do |p|%>
<%=p.category%>
<%end%>
Two more ways:
Product.select(:category).map(&:category).uniq # Ruby does the work
Product.uniq.pluck(:category) # DB does the work (superior)
For Rails >= 5.1 use:
Product.distinct.pluck(:category) # DB does the work (superior)
...because Relation#uniq was deprecated.
I think you can do this:
<% Products.select("DISTINCT(CATEGORY)").each do |p| %>
<%= p.category %>
<% end %>
Source: http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields
This does all the work in the database server. The result is a simple array.
<% Product.distinct(:category).pluck(:category).each do |category|
<%= category %>
<% end %>
Rails will generate SQL that works on any database (Postgres, MySQL, etc).
SELECT DISTINCT "products"."category" FROM "products"
I suggest to use Products.all.distinct.pluck(:category) because uniq has been deprecated since rails 5 and it will be removed on rails 5.1
Try this (in the rails console)
Product.group(:category)
Product.group(:category).each { |p| p.name }
For postgres
<% Product.select("DISTINCT ON (category) *").each do |category|
<%= category %>
<%= name %>
<% end %>
Update
even better
<% Product.select(%(DISTINCT ON (category) "#{Product.table_name}".*)).each do |category|
<%= category %>
<%= name %>
<% end %>
because it can return wrong columns when you do joins (e.g. returns id column from joined table, but not products)
If you or anyone want to get two or more attributes from a table like products, based on a distinct feature of an attribute, only this solution will help you for Rails >= 5.1
distinct_products = Product.select("DISTINCT ON (category) *")
# it's an active record relation class.
> distinct_products.class
=> Product::ActiveRecord_Relation
N.B. Don't use .pluck() on the distinct_products. It will reselect from the products table and the distinct feature will not work anymore.
Needed to get unique output and was trying the 'uniq' method unsuccessfully. Tried several solutions posted here unsuccessfully. I'm using devise which gives me access to the current_user method and working with two tables, one being a join (an item has_many :things).
This solution ultimately worked for me :
#current_user.things.select(:item_fk).distinct.each do |thing|
<%= thing.item.attribute %>
<% end %>

Rails form select with NULL (no choice) support

How can I add a NULL option to my form select? I have a table:
categories
id
category_id
name
If I'm creating a new category, I want to be able to select the NO_CATEGORY option (NULL value and id).
My view code:
<%= f.collection_select :supercategory_id, Category.all, :id , :name %>
Also, it is a good idea? Isn't it better to have some predefined ROOT category in the database? Thank you.
Try:
<%= f.collection_select :supercategory_id, Category.all, :id , :name, :include_blank => true %>
Its ok to have null. Just have your model logic know that it should create a new category and assign it rather than mass assign from the select. Might be something that happens in a before_validation method

rails complex table

i'm having a huge problem with creating this table.
I have a model
Unit
id
floor
unitnumber
here is my current code for view
<% block.units.each do |unit| %>
....
<% end %>
I need to loop through the entire block, get all the unique unitnumber and floor. Create a table like this.
BLOCKNO Unitnumber1 Unitnumber2 Unitnumber3 Unitnumber4 Unitnumber5 Unitnumber6
Floor10 unit_id unit_id unit_id unit_id
Floor9
Floor8
<% block.each do |block| %>
<% block.units.each do |unit| %>
...
<% end %>
<% end %>

Groups and subgroups in Rails

I'm currently sorting products based on release date this way:
<% #product_months.each do |month, products| %>
<h2><%= month.strftime("%B %Y") %></h2>
<% products.each do |product| %>
<p><b><%= product.title %></b> on <%= product.street_date.to_date.to_s(:long) %></p>
<% end %>
<% end %>
In the controller:
#products = Product.where('street_date > ?', Date.today).order('street_date ASC')
#product_months = #products.group_by { |t| t.street_date.beginning_of_month }
Products, though, are also grouped into three sales_seaons, spring, summer and fall. I'd like to further group the items into their seaons, like this. Year > Season > Product, instead of Month > Product, but the grouping is proving a little too complicated for me to get. Any thoughts?
Scopes are your friend. They add class level methods to the model they're defined in. The best part about them is that they're chainable.
There are many ways to get the groupings you're talking about but here's what I would start with.
class Product
# ... your code here
scope :by_sales_season, lambda {|season| where('sales_season = ?', season}
scope :by_year, lambda {|year| where('street_date >= ?' DateTime.now(year) }
# ... more of your code
end
Then in your controller you could:
#products = Product.by_year(2012).by_sales_season("spring")
Of course this will not return to all products across every year and/or every season, though the scopes could be modified to do such a thing, or you could loop over the years and seasons accordingly. However, if you do it this way versus using the group_by method which is an Enumerable method then you don't risk pulling the entire result set into memory when you only want a subset of it.

how to get x most recent records from two tables at once

I have two tables: one for posts and one for topics:
posts: id, topic_id, content, created_at, updated_at
topics: id, title, content, created_at, updated_at
I want to retrieve x most recent records from both of them based on updated_at column. So in the end I expect to have them in ONE collection consisted of BOTH Post and Topic type objects. I hope I made myself clear.
Looks like I haven't made myself clear enough in the end. But in meantime I came up with solution. It's not perfect but it works.
def recent_activities(count: 10)
posts = Post.order(updated_at: :desc).limit(count)
topics = Topic.order(updated_at: :desc).limit(count)
activities = posts + topics
activities.sort! { |x, y| y.updated_at <=> x.updated_at }
activities.first(count)
end
So, as you can see post.topic_id and topic.id association is not relevant. There are two tables which just happens to both have updated_at columns. I need recent X records from group consisted of posts and topics - in snipped above called activities.
since you already have the associations, why not just:
<% Topic.order(:created_at => :asc).limit(10) do |topic| %>
<%= topic.title %>
<%= topic.content %>
<%= topic.post.content %>
<%= topic.created_at %>
<%= topic.post.created_at %>
<% end %>