/products/index.html.erb
<div class="hide-for-small panel">
<h3>Sidebar</h3>
<h5 class="subheader">Feature Product</h5>
<% Product.random do | product | %>
<%= image_tag(Product.image_url) %>
<h5><%= link_to Product.title, product %></h5>
<p><%= button_to 'Add to Cart', line_items_path(:product_id => product) %></p>
<% end %>
</div>
/models/product.rb
def Product.random
self.limit(1).offset(rand(self.count)).first
end
Trying to pull a random product using Postgres. The query comes through in the console but I get no view results in the index.
Any solutions or different ways of accomplishing this?
The whole issue is you're passing a block to a method that doesn't take a block, so its silently ignored, and never executed, so the other problems you have don't come up.
All of your code sits inside a block which you're passing to Product.random via Product.random do |product|. That should be product = Product.random with no do/end block.
Once you've done this, you'll start seeing more errors as you're using Product.title instead of product.title etc.
It looks like your product in your image_tag and link are incorrectly referencing the model and not the random one.
Try changing these:
<%= image_tag(product.image_url) %>
<h5><%= link_to product.title, product %></h5>
You should really generate the random product in your controller and access an instance variable in your view.
Something like:
controller's index action:
#random_product = Product.random
view:
<%= image_tag(#random_product.image_url) %>
etc.
You should never access the model directly from the view.
First of all, you're mixing up class methods with instance methods. Try making the view:
<div class="hide-for-small panel">
<h3>Sidebar</h3>
<h5 class="subheader">Feature Product</h5>
<%= image_tag(#product.image_url) %>
<h5><%= link_to #product.title, #product %></h5>
<p><%= button_to 'Add to Cart', line_items_path(:product_id => #product.id) %></p>
</div>
Class methods (Product.random) are defined when you don't need a specific one. So product.title if for a specific product.
Second of all, in your controller for this action, you'll need to define the #product instance variable as #product = Product.random. And then you can use that in the view.
Third of all, getting a random record could be simplified to:
Product.order("RANDOM()").first
So your model code would look like:
def self.random
Product.order("RANDOM()").first
end
Related
Rails each do method is acting strangely and I do not know why.
controller
def index
#fabric_guides = FabricGuide.with_attached_image.all.order(:name)
end
index.html.erb
<div class="guide-items">
<%= #fabric_guides.each do |fabric| %>
<div class="guide-container">
<%= link_to fabric_guide_path(slug: fabric.slug) do %>
<%= image_tag fabric.image if fabric.image.attached? %>
<% end %>
<div class="guide-info">
<p class="g-name">
<%= link_to fabric.name,
fabric_guide_path(slug: fabric.slug) %>
</p>
</div>
</div>
<% end %>
</div>
I have two FabricGuide records so I expect two "guide-container" but I get three. Or more precisely I get two guide containers and a third block of text containing all the content from the last FabricGuide record.
I have almost an identical setup for articles and have never encountered this problem. I'd happily share more information if needed. Thank you!
Please remove = equal sign from your each loop of view code
like below :-
<% #fabric_guides.each do |fabric| %>
...
...
<% end %>
you have used this <%= #fabric_guides.each do |fabric| %> in your view that's why it shows all record in DOM.
The expression for erb tags is <% %>
now if we want to print that tag too then we apply <%= %>
I am trying to create a todo app that will allow the user to create lists and then "todo" items under each list. However, I want each user to only be able to see his or her lists. While I've been able to partially solve it using the current_user helper, the index page shows empty space where the other users lists are hidden.
Below please find the code for the index.html.erb page inside my todo_lists views.
<% #todo_lists.each do |todo_list| %>
<div class="index_row clearfix">
<% if todo_list.user == current_user %>
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
<% end %>
</div>
<% end %>
<div class="links">
<%= link_to "New Todo List", new_todo_list_path %>
</div>
Here's my repo on Github, in case you need to see more of the code: https://github.com/jramoscolon/todo
Is there a way to hide these empty spaces, as well as the non-matching todo items?
Given your current view code, you are indiscriminately emitting <div class="index_row clearfix"> elements, even when the todo_list.user does not match the current_user. Simply move the whole<div> outside the current_user check, like so:
<% #todo_lists.each do |todo_list| %>
<% if todo_list.user == current_user %>
<div class="index_row clearfix">
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
</div>
<% end %>
<% end %>
This way, all of those empty <div> elements aren't included on the page. This should clean up all that empty space.
If your index view is user specific than the instance variable you want should be user specific as well.
Instead of #todo_lists = ToDoList.all
Use the current_user.todo_lists functionality supplied by your has_many/belongs to
I am trying to make an app with Rails 4.
I have installed the public_activity gem.
I followed the Ryan Bates Railscast and took the controller based approach, and also the lighter Common option (as opposed to tracking the Model).
In my activities_controller I have:
class ActivitiesController < ApplicationController
def index
#activities = PublicActivity::Activity.order("created_at desc")
end
end
In my project.rb, I have:
include PublicActivity::Common
In my projects controller, create action, I have:
#project.create_activity :create, owner: current_user
In my activity view - index, I have:
<% Activities.each do |activity| %>
<div class="col-md-4">
<div class="indexdisplay">
<span class="indexheading">
<%= link_to activity.owner.name, activity.owner if activity.owner %>
</span>
<span class="indexsubtext">
<%= render_activity activity %>
</span>
In my public activity (view folder)/project/_create.html.erb, I have:
<% if activity.trackable %>
<%= link_to activity.trackable.name, activity.trackable %>
<% else %>
which has since been removed
<% end %>
When I try this, I get this error:
NameError at /activities
uninitialized constant ActionView::CompiledTemplates::Activities
I tried replacing the opening line of the activity#index so that Activities, is Activity, but it just changed the error message to:
NameError at /activities
uninitialized constant ActionView::CompiledTemplates::Activities
What does this error mean? How do I fix it?
Thank you
It seems like you use Class in your loop. Try to use your instance variable in your controller.
Change this
<% Activities.each do |activity| %>
into
<% #activities.each do |activity| %>
It should be <% Activity.find_each do |activity| %>
Model name always is singular
You cannot call each just on Model
I'd recommend you use find_each instead of each in case you have a lot of records
if you do want all the records you can always use .all method
http://apidock.com/rails/ActiveRecord/Batches/ClassMethods/find_each
I want to order the Conversation model, using a custom method.
I found some solution:
How do you order by a custom model method that has no attribute in SQL?
and
http://awaxman11.github.io/blog/2013/10/11/sorting-a-rails-resource-based-on-a-calculated-value/ ,
but Conversation order have priority.
First- answer_percent desc,
second- order to last_answer time
(using custom model method last_answered_to_i ).
last_answered_to_i method source:
def last_answered_to_i
if Conversation.where(company_id: self.id, is_answered: true).present?
last_conversation = Conversation.where(company_id: self.id, is_answered: true).first
if last_conversation.answered_at.blank? || last_conversation.asked_at.blank?
minutes = (Time.now- last_conversation.updated_at)/1.minutes
else
minutes = (last_conversation.answered_at - last_conversation.asked_at)/1.minutes
end
minutes.to_i
else
nil
end
end
after ordering I want add pagination using kaminari gem.
#lists = Company.searchable.order("answer_percent desc").page(params[:page]).per(20)
How do I order by column and custom method and add pagination?
I think the answer depends on what you want to see in the view because some of the problem could actually be solved in how you call #lists there. Also, some of the links you found make sorting by a model method sound more difficult than it is.
In your case, you can sort your conversations by a custom method like so:
Conversation.all.sort_by(&:custom_method)
Or specifically:
Conversation.all.sort_by(&:last_answered_to_i)
Specifically, you cannot use SQL to sort or order by something not in the actual database, so you use the Ruby sort_by method. For more info on the ampersand, see this post.
For your actual view, I'm not sure really how you want to organize it. I recently did something where I needed to group my resource by another resource called "categories", and then sort the original resource by "netvotes" which was a custom model method, then order by name. I did it by:
Ordering by name in the controller: #resources = Resource.order(:name)
Grouping by category in the outer loop of the view: <% #resources.group_by(&:category).each do |category, resources| %>
Then sorting the resources by votes in the partial for resources: <%= render resources.sort_by(&:netvotes).reverse %>
The view is a bit confusing, so here is the full view loop in index.html.erb:
<% #resources.group_by(&:category).each do |category, resources| %>
<div class="well">
<h3 class="brand-text"><%= category.name %></h3>
<%= render resources.sort_by(&:netvotes).reverse %>
</div>
<% end %>
And here is the _resource.html.erb partial:
<div class="row resource">
<div class="col-sm-2 text-center">
<div class="vote-box">
<%= link_to fa_icon('chevron-up lg'), upvote_resource_path(resource), method: :put %><br>
<%= resource.netvotes %><br>
<%= link_to fa_icon('chevron-down lg'), downvote_resource_path(resource), method: :put %>
</div>
</div>
<div class="col-sm-10">
<%= link_to resource.name, resource.link, target: "_blank" %>
<p><%= resource.notes %></p>
</div>
</div>
I hope that helps you think through some more ways to address your problem.
While trying to build a form to create new items on an index page rather than the new view, i ran into a curious problem.
When presenting the form for creation of a new task in the current project, the #tasks variable that contains the tasks that are supposed to be displayed in the list below, seems to be empty. Therefore i get a "No route matches" since the object im passing to ie. complete_project_task_path is nil.
When removing the form, everything works like a charm. Any ideas why this happens?
<h1>Listing tasks</h1>
<%= form_for([#project, #project.tasks.build]) do |f| %>
<div id="new_quick_task">
<%= f.text_field :title, :value => 'Quickly add a new task' %>
<%= f.submit %>
</div>
<% end %>
<div id="task_list">
<% #tasks.each do |task| %>
<div class="task">
<div class="completed"><%= task.completed %></div>
<div class="complete_link"><%= link_to "Good", complete_project_task_path(#project, task) %></div>
<div class="title"><%= link_to task.title, project_task_path(#project, task) %></div>
</div>
<% end %>
</div> <!-- end task_list -->
Why do you use #tasks and not #project.tasks? because it would show the new task you created for your form?.
Well, you could still use #project.tasks and do something like:
<% #project.tasks.each do |task| %>
<% unless task.title.nil? %>
<div class="task">
<div class="completed"><%= task.completed %></div>
<div class="complete_link"><%= link_to "Good", complete_project_task_path(#project, task) %></div>
<div class="title"><%= link_to task.title, project_task_path(#project, task) %></div>
</div>
<% end %>
<% end %>
which would skip the tasks without the title.
The error you get is not because the #tasks variable is empty, because if it was, you would never come to the code below it. The error you get is that one of the items inside your #tasks contains a value it does not expect. I guess it has something to do with your complete_project_task_path(#project, task) that will check something of task that is not set correctly?
So i think i figured it out. (please correct me if im wrong)
Ruby variables hold references to
objects and the = operator copies the
references.
(from http://ruby-doc.org/docs/Newcomers/ruby.html#objects no. 17)
Taking that into account, look at the following example
#task_list = #project.tasks
This essentially makes #task_list refer to the same object as #project.tasks. If the data in #project.tasks changes, so does #task_list's data because they both point to the same object.
#project.tasks.build seems to alter the object, that both #project.taks and #task_list point to, in some way.
The solution was pretty simple. Instead of setting #task_list = #project.tasks i created a new object for #task_list.
So in the controller, istead of doing this:
#project = Project.find(params[:project_id])
#task_list = #project.tasks
just do it like this:
#project = Project.find(params[:project_id])
#taks_list = Task.where(:project_id => #project.id)