Rails 4 has_many relation group by - has-many

Guys how I can fixed this issue
I need to get the result of the relation and group the result using the user_id
My main loop something like that
<% if #users.count >0 %>
<% #users.each do |user| %>
<% if user.books.present? %>
<% user.books.each do |book| %> <!----this is the query I want to change---------->
<% if book.user.present? %>
id | <%= book.user.id %>
user | <%= book.user.user_name %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
I'm tried to used a lot of statements like
<% user.books.group_by(&:user_id).each do |book| %>
<% user.books.group_by(&:user_id).uniq.each do |book| %>
<% user.books.group_by(&:user_id).distinct().each do |book| %>
<% user.books.group_by{|us| us.user_id}.each do |book , us| %>
instead of the statement
<% user.books.each do |book|%>
but usually I get issues , so how i can group by array or DB relation in one statement ?

If the issue is that you are experiencing "nil" call errors when you reference user.books.each, you might do this:
<% user.try(:books).each do |book| %>
This allows you to capture the error rather than fall through to the default error handler.
Otherwise, supposing that you have created a has_many and belongs_to relationship, you definitely ought to be using:
user.books.each {|b| }
This will give you books grouped by users.

Related

Middleman shows syntax error when using a link_to block

I'm using Middleman 4.2 with Middleman-blog 4.0.2.
When I have:
<% blog.tags.each do |tag, articles| %>
<%= link_to "#{tag.titleize} - #{articles.size}", tag_path(tag) %>
<% end %>
I get the desired <a> element output:
Test Tag - 1
But when I change the link_to to a block:
<% blog.tags.each do |tag, articles| %>
<%= link_to tag_path(tag) do %>
<%= tag.titleize %> - <%= articles.size %>
<% end %>
<% end %>
I get a syntax error:
/source/blog/index.html.erb:43: syntax error, unexpected ')' ...<< ( link_to tag_path(tag) do ).to_s; #_out_buf << '
I can't seem to figure out why I'm not able to get the same output here.
Any pointers?
I just realized I had the wrong erb tag on the line with the link_to helper.
The correct code looks like this:
<% blog.tags.each do |tag, articles| %>
<% link_to tag_path(tag) do %>
<%= tag.titleize %> - <%= articles.size %>
<% end %>
<% end %>

Tell <%= ... %> not to add a space

I use the following code in a template to render a date:
<% if job.end_month do %>
<%= "#{job.end_month}/" %>
<% end %>
<%= "#{job.end_year}" %>
This results in 3/ 2014 and not in 3/2014. How can I force Phoenix not to add a space after "#{job.end_month}/"?
One solution would be to create an external helper that did this for you:
e.g.
def job_string(%Job{end_month: nil}), do: job.end_year
def job_string(job), do: "#{job.end_month}/#{job.end_year}"
Then just use that in your view:
<%= job_string(job) %>
Alternatively if you don't want to do all that and would prefer a messier sort of look:
<% if job.end_month do %>
<%= "#{job.end_month}/#{job.end_year}" %>
<% else %>
<%= "#{job.end_year}" %>
<% end %>

How to save many items on one form rails?

I need to save many items to Cart on form, user enter quantity one form, and selected items goes to db, but now save only first entered quantity of item. Why?
my form
<%= form_for #cart_item do |f| %>
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, :value => item.id %>
<%= f.text_field :qty %>
<% end %>
<%= f.submit %>
<% end %>
And controller
cart_items_controller.rb
class CartItemsController < ApplicationController
before_action :set_cart, only: [:create]
def create
#cart_items = CartItem.create(cart_items_params)
#cart_items.cart_id = #cart.id
if #cart_items.save
redirect_to :back
else
render root_path
end
end
private
def cart_items_params
params.require(:cart_item).permit(:id, :qty, :item_id, :cart_id)
end
def set_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
There are a few problems here. I'll give you a little bump:
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, :value => item.id %>
<%= f.text_field :qty %>
<% end %>
For each CartItem, this is going to create an input like this
<input name="qty">
This is problematic because only one (the last one in the DOM) will be submitted. You need to research fields_for and incorporate that into your loop in order to get unique names for each Item in the form.
This same issue follows through into your controller
def cart_items_params
params.require(:cart_item).permit(:id, :qty, :item_id, :cart_id)
end
This is going to look for a single :id, :qty, :item_id, and :cart_id, when in reality you're looking to accept multiple :item_id and :qty fields. You need to research Strong Parameters with nested has_many associations.
Finally you have this
#cart_items = CartItem.create(cart_items_params)
which is going to attempt to create a single CartItem when you're really trying to create multiple items and associate them back to the Cart. You need to research accepts_nested_attributes_for as well as more generally "rails form save has_many association". It's a widely covered topic here on SO and elsewhere.
I do this:
def create
#cart_items = params[:cart_items]
#cart_items.each do |c|
#cart_item = CartItem.new(c)
if #cart_item.qty.present?
#cart_item.cart_id = #cart.id
#cart_item.save
end
end
and form
<%= form_tag cart_items_path do %>
<% #cart_items.each do |cart_item| %>
<%= fields_for "cart_items[]", cart_item do |f| %>
<% #category.items.each do |item| %>
<%= item.name %>
<%= f.hidden_field :item_id, value: item.id %>
<%= f.text_field :qty %>
<% end %>
<%= f.submit %>
<% end %>
<% end %>
<% end %>

Conditional statement in "each...do" in Ruby?

In my erb file, I have the following code in the body tag:
<% #tasks.each do |task| %>
<%= task.name %>
<% end %>
This is working, but I only want to display task.name if task.otherAttribute does not equal -1.
For some reason, I can't figure out how to do this! Any tips much would be much appreciated.
Thank you in advance.
Try this:
<% #tasks.each do |task| %>
<%= task.name if task.otherAttribute != 1 %>
<% end %>
Or:
<% #tasks.each do |task| %>
<%= task.name unless task.otherAttribute == 1 %>
<% end %>
I will provide some more options for future reference:
<% #tasks.each do |task| %>
<% if task.otherAttribute != 1 %>
<%= task.name %>
<% end %>
<% end %>
<% #tasks.each do |task| %>
<%= task.otherAttribute == 1 ? '' : task.name %>
<% end %>
Good luck!
I tend to use #select and #reject for this idiom, since that's basically what you're doing.
<%= #tasks.reject{|t| t.other_attribute == -1}.each do |task| %>
<%= task.name %>
<% end %>
These come from the Enumerable module, which most things with an #each method include.
You can put conditionals into your ERB code.
<%= task.name if task.otherAttribute != 1 %>
You can also perform more complex tasks with a more verbose syntax. It's not necessary in your case, but you could also do more traditional if/else blocks like so:
<% if task.otherAttribute != 1 %>
<%= task.name %>
<% end %>

Facebooker2 returning users UID but not name

I am just using the standard Facebooker2 setup.
<%= fb_connect_async_js %>
<% if current_facebook_user %>
<%= "Hello #{fb_name(current_facebook_user, :useyou => false)}!" %>
<%= fb_logout_link("Logout", request.url) %><br />
<% else %>
<%= fb_login_and_redirect('/login', :scope => 'user_about_me') %>
<% end %>
What displays on the page is:
Hello <fb:name uid="73648576" useyou="false"></fb:name>
I am sure there's something very basic wrong here, but I've followed the instructions, done tutorials, wetc. and continue to get this result.
Any help most appreciated!
Not sure why fb_name isn't working, but you could use the other method as specified in the readme. In this case, you need to call the fetch method on current_facebook_user first:
<% if current_facebook_user %>
<% current_facebook_user.fetch %>
<%= "Welcome #{current_facebook_user.first_name} #{current_facebook_user.last_name}!" %>
Ref: http://www.engineyard.com/video/21045039 (around 9:36)

Resources