So Im listing out all the members of my site and grouping them by name so that the list will be organized better. So in my view all my members are grouped by the first letter of their member name like:
B
Bakedfish
Beercan Dan
Bigmike33x
C
Cynicalassassin
ect..
Anyway, I also want to paginate this list but I cant add Kaminari's pagination arguments to my controller if Im using order because I get an undefined method error.
so this doesnt work:
#members = Member.all.group_by{|u| u.fullname[0].titleize}.page(params[:page]).per(18)
my view looks like this:
<div class="content">
<%= paginate #members %>
</div>
<% #members.keys.sort.each do |starting_letter| %>
<h3>
<%= link_to starting_letter, {:action => :browse, :controller =>:members, :letter => starting_letter } %>
</h3>
<ol>
<% #members[starting_letter].each do |member| %>
<li>
<% if member.is_artist? %>
<%= link_to member.full_name, member_path(member), :class=>"artist" %>
<% else %>
<%= link_to member.full_name, member_path(member) %>
<% end %>
</li>
<% end %>
</ol>
<% end %>
Here is my error message:
NoMethodError (undefined method `page' for #<Hash:0x007f78d4bf48f8>):
app/controllers/members_controller.rb:10:in `index'
Kaminari adds page method to ActiveRecord::Relation but Member.all.group_by returns hash. That is why you get this exception.
I'd suggest to perform grouping after pagination, e.g.:
#members = Member.order(:full_name).page(params[:page]).per(18).to_a.group_by { |u| u.fullname[0].upcase }
UPDATE
In order to use paginate helper you could assign 2 variables, e.g.:
#paginated_members = Member.order(:full_name).page(params[:page]).per(18)
#members = #paginated_members.to_a.group_by { |u| u.fullname[0].upcase }
And pass #paginated_members to the paginate helper.
Related
I have a loop that looks like this
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= collection.stories.count %>
<% end %>
It works perfectly to show the Collections that belongs to a User, and then show how many Stories are in each Collection.
However, I want to use a helper that does this.
in the view
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= number_of_stories_in_collection %>
<% end %>
in the helper
module CollectionsHelper
def number_of_stories_in_collection
collection.stories.count
end
def render_stories_count
if number_of_stories_in_collection.zero?
'No stories in this collection yet'
else
"#{number_of_stories_in_collection} #{'story'.pluralize(number_of_stories_in_collection)}"
end
end
end
I get an error that says
undefined method `stories' for #<Collection::ActiveRecord_Relation:0x007f510f504af8>
Any help is appreciated, thanks!
The 'collection' variable isn't an instance variable, so the helper can't see it.
Change your view to this:
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= number_of_stories_in(collection) %>
<% end %>
And your helper method to:
def number_of_stories_in(collection)
collection.stories.count
end
This way you are passing the variable to the helper correctly.
extending #Richard's answer and little bit of optimisation to avoid n+1 queries..
<% #user.collections.includes(:stories).each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= render_stories_count(collection) %>
<% end %>
helper:
module CollectionsHelper
def number_of_stories_in(collection)
collection.stories.length
end
def render_stories_count(collection)
if (count = number_of_stories_in(collection)).zero?
'No stories in this collection yet'
else
"#{count} #{'story'.pluralize(count)}"
end
end
end
I'm using the following code to display posts to my users.
_feed.html.erb partial:
<% #posts_by_month.each do |monthname, posts| %>
<%= monthname %>
<ul>
<% posts.each do |post| %>
<li><%= post.created_at %></li>
<% end %>
</ul>
<% end %>
Controller:
def home
if logged_in?
#post = current_user.posts.build
#posts_by_month = current_user.feed.group_by { |post| post.created_at.strftime("%B") }
This renders my posts as follows:
Post 1
Post 2
Post 3
Post 4
I want to change it so that the posts are displayed like:
Post 1 Post 2 Post 3
Post 4 etc etc
etc
I've tried several approaches to this, including the in_groups_of(3) method however the way it is currently setup means nothing works. I feel like there is an obvious solution I'm missing - can anyone help?
[Edit to expand on the in_groups_of(3) error]
If I change line 4 in the _feed partial to:
<% posts.in_groups_of(3, false).each do |post| %>
It gives the error: undefined method `created_at' for #< Array:0xbb8f258 >
The #in_groups_of method returns an Array of Arrays each containing 3 Post objects.
So you now also need to iterate over the returned array that contains your three Posts, something like:
<% posts.in_groups_of(3, false).each do |post_group| %>
<% post_group.each do |post| %>
<li><%= post.created_at %></li>
<% end %>
<% end %>
You can use facets gem. This provides and each_by method. You can use each_by to create groups and iterate further on these groups.
Here is code snippet on how to use each_by
<div class = "small-9 columns vertical-border-left">
<%- #client.contact_details.each_by(3) do |contact_details| %>
<div class="row">
<%- contact_details.each do |contact| %>
<div class="small-3 columns small">
<div> <%= contact.contact_detail_type %> contact </div>
<div> <%= contact.contact_email %> </div>
<div> <%= contact.contact_phone %> </div>
</div>
<% end %>
</div>
<% end %>
</div>
I have a classes User and Company, I want to re-use the users partial as the to render company staff.
In my CompaniesController I have:
def staff
#company=Company.find(params[:id])
#users=#company.works_fors.paginate(page: params[:page], :per_page => 10)
#title=#company.name+" staff."
end
And in my staff.html.erb template I have:
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
This is the works_fors/_works_for partial:
<%= render :partial => 'user' %>
Which Renders
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.developer? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
However this throws an error on the user object as it cant find the method
undefined local variable or method `user' for~~
I think this is because Im calling the user object from within companies but there is a defined relationship, or do I need to redefine in companies ?
It's hard to tell, but it appears that what you call #users in your controller is in fact not a User collection, but a WorkFor collection.
#users = #company.works_fors...
What you mean is:
#works_fors = #company.works_fors...
This means that staff.html.erb is working with a works_for collection. So you should rename the variable in your template to avoid confusion.
# staff.html.erb
<% if #works_fors.any? %>
<ul class="users follow">
<%= render #works_fors %>
</ul>
<%= will_paginate #works_fors %>
<% end %>
Now we know we are rendering a works_for partial. So an instance of works_for is be available inside the partial. We need to ask it for its associated user instance, and pass it to the render method.
# works_fors/_works_for.html.erb
<%= render works_for.user %>
As a bonus, you can save yourself some queries by preloading the users.
#works_fors = #company.works_fors.includes(:user)...
How do I display products from the ShopSense API in Rails using shopsense-ruby?
JSON.parse(response)["products"] is returning nil:
NoMethodError in Main#index
Showing /home/dev/demo-shopsense/app/views/shared/_shopsense.html.erb where line #3 raised:
undefined method `any?' for nil:NilClass
Extracted source (around line #2):
<div class="custom_widget">
<% if #products.any %>
<% #products.each do |product| %>
<div class="product">
<%= image_tag product['image']['url'] %>
<p><%= product['name'] %></p>
main_controller.rb:
class MainController < ApplicationController
def index
client = Shopsense::API.new('partner_id' => 'uid0000-0000000-00')
response = client.get_looks("New")
#products = JSON.parse(response)["products"]
end
end
shared/_shopsense.html.erb:
<div class="custom_widget">
<% if #products.any? %>
<% #products.each do |product| %>
<div class="product">
<%= image_tag product['image']['url'] %>
<p><%= product['name'] %></p>
</div>
<% end %>
<% end %>
</div>
I've set up a simple demo app demo-shopsense that should be easy to get up and running.
The parsed response of your request looks like this:
{"totalCount"=>"536121",
"looks"=>
[{"id"=>"12328367",
"title"=>"black",
...
As you can see instead of 'products' we have 'looks'.
#products = JSON.parse(response)["looks"]
When you are working with external services, it's very important to find out the exact format of the response.
EDIT:
I think in this case you actually need to use 'search' method on the client instead of 'get_looks', if you want to get products.
helpers/subcategories_helper.rb:
module SubcategoriesHelper
def has_topic_headings?
self.topic_headings
end
end
categories/show.html.erb contains
<% #category.subcategories.each do |subcategory| %>
<li>
<h6>
<%if subcategory.has_topic_headings? %>
<%= link_to subcategory.name, subcategory, data: :has_topic_headings %>
<% else %>
<%= link_to subcategory.name, subcategory %>
<% end %>
</h6>
<hr>
</li>
<% end %>
The page returns
undefined method `has_topic_headings?' for #<Subcategory:0xa68748c>
Please note that the view page belongs to the Category, not the Subcategory.
You are trying to call it on model which is why it is not called on when helper is included. Helpers are there for views and sometimes for controllers.
Here is your method :
<%= link_to subcategory.name, subcategory, data: :has_topic_headings %>
Edit: Sorry for misunderstanding. the error is in your data which you are passing in your link:
data: :has_topic_headings
rails is asking for above method, not for has_topic_headings?
Edit: Yes, as #techvineet said, you cannot call a helper method on a subcategory object.
you should write method in your subcategory model:
def has_topic_headings?
return true if self.topic_headings
end
Or you can do this in your helper class:
def has_topic_headings(subcategory)
return true if subcategory.topic_headings
end
and in your form, call it like this:
<%if has_topic_headings(subcategory) %>
<%= link_to subcategory.name, subcategory, data: :has_topic_headings %>
<% else %>
<%= link_to subcategory.name, subcategory %>
<% end %>
Hope it will help.Thanks