Rails how to map name and id from array? - ruby-on-rails

If I am getting parent nodes via and outputting them as a sort of bread crumb list, how do I map both the name of the classification and id to bu8ild a link_to?
<% #parents.map(&:name).each do |parent| %>
<%= link_to parent, new_sr_path(class_id: parent, sub: :true), class: "form-control" %><svg ...</svg>
<% end %>
#parents = #classification.ancestors.to_a.reverse if params[:class_id].present?

You should iterate through your objects, instead of the names of your objects (generated by the .map(&:name) call):
<% #parents.each do |parent| %>
<%= link_to parent.name, new_sr_path(class_id: parent.id, sub: :true), class: "form-control" %>
<% end %>
NOTE Having a real instance give you the ability to call all instance methods defined on that object: parent.name, parent.id, ...

Related

Rails: pass an array to a scope

I'm trying to figure out how to let a user enter multiple "skills" in a text area separated by comma's and then have those skills turned into an array that feeds into a scope one at a time.
Also on my index view I'm listing the skills in the array so that when a user clicks on one it will actually remove that skill as a filter.
The issues that i'm having are
1) not sure I'm doing the array correctly the way i have it now
2) in the index view when you click on just one skill to remove, all skills are removed.
in my form
<p>
<%= label_tag(:sk, "Skills:") %>
<%= text_area_tag :sk, params[:sk], placeholder: "Enter skills", class: "form-control" %>
</p>
in my controllers index action
# filters on the users skills
if params[:sk].present?
#skills_list = params[:sk].split(",")
#skills_list = #skills_list.to_a
#skills_list.each do |skill|
#users = #users.by_skills_array(skill)
end
end
in my user model I call the scope (The skill model is separate but belongs_to the user model so that's why i'm doing the join).
scope :by_skills_array, -> (skill) { joins(:skills).distinct.where( 'skills.name LIKE ?', "%#{skill}%" ) }
in my index I'm doing
<% if params[:sk].present? %>
<% #skills_list.each do |skill| %>
<%= link_to users_path( c: params[:c], ex: params[:ex], s: params[:s], lang: params[:lang], cert: params[:cert],
u: params[:u], relo: params[:relo], ed: params[:ed], maj: params[:maj], job: params[:job] ) , class: "btn btn-default" do %>
<i class="fa fa-times"></i> <%= "#{skill}" %>
<% end %>
<% end %>
<% end %>
here's the output

second parameter content_tag rails

I have a dropdown in the form i'm using
<%= f.select(:visitable_id) do %>
<% #visitors.each do |visitor| %>
<%= content_tag(:option, visitor.name, value: visitor.id, data: {:type => visitor.class.name.to_s} ) %>
<% end %>
<% end %>
When submitted I get the visitable_id in the controller. But I would also like to receive the data of the data value in the content_tag. The: data: {:type => visitor.class.name.to_s}
How can you access the second value in the controller? Any help would be appreciated!
HTML5 data attributes are not sent with the form. Nor is anything else except the name and value of the inputs.
You could solve it by passing both values through a single option.
<%= f.select(:visitable_id) do %>
<% #visitors.each do |visitor| %>
<%= content_tag(:option, visitor.name, value: "#{visitor.class.name}=visitor.id") %>
<% end %>
<% end %>
You can then parse them out by splitting the string:
klass, id = params[:visitable_id].split('=')
But make sure you whitelist the acceptable values for klass to avoid a vulnerability where a malicious user can query any model.

getting message School:0x00559eba30b8b8 instead of displaying school name

I'am trying to display school name which is related to members, but I got the School:0x00559eba30b8b8, instead the name.
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school %>
<% end %>
result : John john#john.com #School:0x00559eba30b8b8
update:
with school_id I get the id of the school, but still don't know how to get the name.
How can I get the name of the school?
Many thanks
Since school is not mandatory attribute, it can’t be just queried for the name, one should use try there:
<%= member.school.try :name %>
Assuming you have school_id in members table you need to print school.name instead of school
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school.try(:name) %>
<% end %>
NOTE: member.school will return you an instance of School and you want to print just name.
Use
<%= member.school.try(:name) %>
Note:- Assuming your school has attribute 'name'
Also in your controller where you finding #members use 'includes', something like
#members = member.where().includes(:school)

Iterating through attributes with index in ruby

How can i add index to iteration on attributes in ruby?
<% #child.toys.attributes.each do |attr_name, attr_value| %>
I have tried with each_with index:
<% #child.toys.attributes.each_with_index do |attr_name, attr_value| %>
But where would the index go in?
You could do this
<% #child.toys.attributes.each_with_index do |(attr_name, attr_value), idx| %>
For more details possible-to-access-the-index-in-a-hash-each-loop
.each_with_index appends the index variable:
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index
}
hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
In your example:
<% #child.toys.attributes.each_with_index do |key,value,index| %>
<%= key %>
<%= value %>
<%= index %>
<% end %>
Toys needs to be a member object (attributes won't work on a collection).
-
I also tested with just declaring "key", as follows:
<% #child.toys.attributes.each_with_index do |attr,index| %>
<%= attr[0] %>
<%= attr[1] %>
<%= index %>
<% end %>
attr is returned as an array in this instance, where the key/value is used as 0 and 1 elements of the array respectively.

group_by display belongs_to 'name' followed by has_many 'items'

I'm trying to display group name (product_group) followed by the items (product) in each group.
<% #products.group_by(&:product_group_id).each do |s|%>
<!--need to get group name here ->
<% s[1].each do |d|%>
<%= d.product_name%>
<br>
<%end%>
<%end%>
rails 2.3.8
First, I strongly recommend using two variables in your block. When you use one variable, group_by sets the variable to an array of the pair of values which should be set as two variables. It will be much more clear code than indexing the pair with [1] for the group.
One way is that the first part of the pair will be the id, so you can do a find.
<% #products.group_by(&:product_group_id).each do |product_group_id, products|%>
<!--need to get group name here -->
<%= ProductGroup.find(product_group_id).name %>
<% products.each do |product|%>
<%= product.product_name%>
<br>
<% end %>
<% end %>
Another way, is since you have an array of at least on product in the group, you can call the product_group association on the first element of the array.
<% #products.group_by(&:product_group_id).each do |product_group_id, products|%>
<!--need to get group name here -->
<%= products[0].product_group.name %>
<% products.each do |product|%>
<%= product.product_name%>
<br>
<% end %>
<% end %>
You can also delegate the name to the product group.
class Product
belongs_to :product_group
delegate :name, :to => :product_group, :prefix => true, :allow_nil => true
end
<%= products[0].product_group_name %>
Group by needs two variables in the block declaration. The first for the thing you are grouping by, and the second to hold the things in each of the groups.
<% #products.group_by(&:product_group_id).each do |group_id, group_products| %>
Group ID: <%= group_id %>
<br>
Products:
<% group_products.each do |product| %>
<%= product.product_name %>
<% end %>
<% end %>

Resources