In my app to learn RoR, I want to get the last x (say 5) records in a list.
Currently I get all using
<% #business_partner.received_documents.each do |document| %>
Looking at documentation and SC posts, I tried using this code below, yet get an empty list.
<% #business_partner.received_documents.last(5) do |document| %>
what should I use?
Order received_documents by the creation date and take 5 last:
#business_partner.received_documents.order(:created_at).limit(5)
To get 5 newest ones you'd do:
#business_partner.received_documents.order(created_at: :desc).limit(5)
EDIT
The problem with this
#business_partner.received_documents.last(5) do |document|
is that you actually do not iterate over the collection, thus no output is shown.
Use each:
#business_partner.received_documents.last(5).each do |document|
You Forget to User each In Your Code
<% #business_partner.received_documents.last(5).each do |document| %>
Related
In my Rails 4 app, I am using paper_trail to track changes made by users on the records of the Post model:
# post.rb
has_paper_trail :on => [:update, :destroy]
A post belong_to a calendar and a calendar has_many post, so I display the changes made to posts in a dashboard located in the calendar index view:
<div id="my_changes">
<% if #versions.any? %>
<% #versions.each do |version| %>
<% version.reify ? post = version.reify : post = Post.find_by_id(version.item_id) %>
<p>
<strong>
<% if version.whodunnit.to_i === current_user.id %>
You
<% else %>
<%= User.find_by_id(version.whodunnit).first_name %>
<% end %>
</strong> <%= conjugate(version.event) %> the post "<%= post.subject %>" in the <em><%= link_to Calendar.find_by_id(post.calendar_id).name, calendar_path(id: post.calendar_id) %></em> calendar <span id="update_time_ago">— <%= time_ago_in_words(version.created_at) %> ago.</span></p>
<% end %>
<% else %>
<p>
<span class="glyphicon glyphicon-hand-up" aria-hidden="true"></span><br/>There is no change to your posts yet.<br/>
As soon as you update your calendar, a history of your changes will appear here.
</p>
<% end %>
</div>
This is working fine.
What I would like to achieve now — and I can't figure out how — is not only to display which post has been updated, but also which attribute of the post has been updated and its value.
For instance, instead of:
User_1 updated the post "Test post" in the Test calendar — 3 days ago.
I would like to have something like:
User_1 updated the date / time / subject / copy / of the post "Test
post" to NEW_POST_ATTRIBUTE_VALUE in the Test calendar — 3 days ago.
—————
UPDATE: I did read paper_trail's documentation, in particular the Choose attributes to monitor section, but this does seem to explain how to achieve what I am trying to achieve.
—————
UPDATE 2: I understand that what I am looking for may actually be explained in the Diffing versions section of the documentation.
So, I guess in my index.html.erb view, I could do something like:
post.versions.last.changeset
But then, how can I extract from there the information that I am interested in, eg: only the attribute that was updated, and its new value, and not the updated_at attribute, that I cannot ignore with paper_trail since I still want to know when the post was updated?
—————
UPDATE 3: in this Stack Overflow thread, #Maysam suggests:
With this behavior enabled, it is reasonably simple to get
object.versions.map{|v| [v.created_at, v.changeset]} and then
iterate over that structure to render your change log.
I am not sure I understand how I can actually iterate over that structure in my case: any suggestion?
—————
Can I actually achieve that with paper_trail?
.. I would like to .. display .. which attribute of the post has been updated and its value.
Per the documentation on Diffing Versions:
.. to diff adjacent versions .. add an object_changes text column to your versions table .. PaperTrail will store the changes diff .. in each update version. You can use the version.changeset method to retrieve it.
So, once you've done that, try adding
= debug post.versions.last.changeset
To your view. After that, if you know how to work with hashes in ruby, you should be good to go.
I want to implement a search functionality in my Rails app by using the pg_search gem. I've set up everything like it says in the documentation. Then I've set up a search controller with a show action:
def show
#pg_search_documents = PgSearch.multisearch(search_params)
end
The search itself works but I have a really annoying problem in my view. Whatever I do, it always outputs an array of PgSearch::Document objects. Even when I only write this in my view:
<%= #pg_search_documents.each do |document| %>
<% end %>
I get this (I've shortened it):
[#<PgSearch::Document id: 2, content: "…", searchable_id: 28, searchable_type: "Vessel">, #<PgSearch::Document id: 3, content: "…", searchable_id: 27, searchable_type: "Vessel">]
I know that pg_search sets up a polymorphic association which I've never dealt with before — could that be the problem?
Thanks in advance
<%= #pg_search_documents.each do |document| %>
<% end %>
This is a classic error, one I remember being puzzled over when I first started learning Rails. The mistake is using <%= %> with each. The return value of each is the array that you're iterating over (in this case, #pg_search_documents), and by using <%=, you're telling Rails to create a string from that array and insert it into your view. That generally isn't what you want: you want the view to be generated by the code inside the block you're passing to each.
Use <% #pg_search_documents.each do |document| %> instead (omitting the =) and you'll avoid the dump of the array's content.
You may also need to use .searchable as #blelump suggests, but I wanted to answer the other half of your question, as it's a common pitfall.
To get back to the original source model, searchable call is needed on these search result records, e.g:
<% #pg_search_documents.each do |document| %>
<%= document.searchable %>
<% end %>
You can also switch back to the source model within your controller, e.g:
#pg_search_documents = PgSearch.multisearch(search_params).collect(&:searchable)
Then, the #pg_search_documents will contain Vessel elements.
I have two models, posts and comments, and i am trying to show the last 5 comment titles.
<%= Post.limit(5).order('created_at desc') %>
gives me the last 5 posts.
How do i get the last 5 comments and just the titles?
For getting just last 5 comments, you can use this
Comment.limit(5).order('created_at desc').select(:title)
Showing the title of the post, it looks like that you want to retrieve the last 5 comments of a post.
You can get this way:
<% Post.limit(5).order('created_at desc').each do |post| %>
<% post.comments.select(:title).order('created_at desc').limit(5).each do |comment| %>
<%= comment.title %>
<% end %>
<% end %>
There are two problems:
You're accessing the model directly from View. You should do it from
Controller
There is N + 1 problem. You can solve it by eager loading associations
Note: I couldn't test these but I guess they will work or will, at least, give you idea.
I think you are looking for:
Comment.select(:title).order('created_at desc').limit(5).map {|c| c.title}
This will give you an array of titles for the last 5 comments created. If you need other attributes, either add them to the select method called (Comment.select([:title, :owner])), or remove the select and fetch all comment attributes.
I'm attempting to create a loop which shows stars as reviews are placed for a product, i have it so that it shows the rating as a number however i wish for it to display an image relating to the rating number,
i've currently got
<%=product.no_of_stars.to_i do image_tag "star-on.png" end %>
however it just displays the rating figure and not the number, no doubt I've missed something simple.
I've researched other questions and they state that should be enough for what i want, but of course its not working as expected.
Thanks, Ben.
The above answer is not quite correct. The problem is that Integer#times returns the integer it was called on, so you will still get 5 as the result. Try
<% product.no_of_starts.to_i.times do %>
<%= image_tag "star-on.png" %>
<% end %>
Try this.
<%=product.no_of_stars.to_i.times do image_tag "star-on.png" end %>
You are missing the times method. This is what allows you to run the number as a loop over and over again (super simplification).
I have an object called #events containing about 50 records being pulled from a find condition of my model.
I'm currently displaying the results of the #object in my view like this....
<% for event in #events %>
<p><%= #event.name %></p>
<% end %>
Instead of displaying the entire 50 I would like shrink the set to about 10 records so it displays better on the page.
I cannot use :limit in the find condition since the object is being composed from a variety of loops where after each iteration it adds a few specific records.
So the issue is I have this object #events with 50 records, how can I change the object after its been composed so only the first 10 records remain?
First of all, if you'd like to have pagination, I strongly suggest taking a look at will_paginate
Alternatively, you can do the following to read the first 10 records only.
<% #events.first(10).each do |event| %>
<p><%= event.name %></p>
<% end %>
Or the last 10 records
<% #events.last(10).each do |event| %>
<p><%= event.name %></p>
<% end %>
I didn't test it but you get the point.
are you looking to completely do away with the other 40 or are you just wanting to pull off 10 per page for display purposes. if you are just doing this for display purposes i would look into the will_paginate gem. through its options you could set it so only 10 results per page are shown.
Take a look at will_paginate and kaminari. They both are designed to limit the records retrieved from the database, plus offer helpers for your views to provide the usual number of pages and current page lists.
Will_paginate has been around a while, and is pretty flexible. Kaminari is newer and looks like it has a cleaner interface.