Only Display Current Month Data - ruby

I have created a functioning e-commerce platform where Members can buy songs and my Index page organizes the data by Month. Everything works fine, But now I would like to strictly display the information for the current month. (In Our Case JUNE).
Currently I am able to list every month's data, but this can become a problem to display when million of songs are being bought throughout the year.
How Can I Only display the current Months Data?
CONTROLLER
def index
#orders = Order.find(:all, :order => 'order_date, id')
end
VIEW
###How can i Only Display Current Month?
<% #orders.sort.group_by { |order| order.order_date.beginning_of_month }.each do |month, orders| %>
<h3><%= month.strftime('%B') %> </h3>
<% orders.group_by { |order| order.song.album.artist }.each do |artist, orders| %>
<h4><%= artist.name %> </h4>
<% orders.group_by { |order| order.song.album }.each do |album, orders| %>
<h5><%= album.name %> </h5>
<% orders.group_by { |order| order.song }.each do |song, orders| %>
<p>(<%= orders.count %>) <%= song.title %> </p>
<p><%= song.price %> </p>
<% end %>
<% end %>
<% end %>
<% end %>

Something like this perhaps? (in your controller)
#orders = Orders.where('created_at < ? and created_at > ?', Time.now.end_of_month, Time.now.beginning_of_month)

Related

How to reduce rails code efficiently?

In Projects controller I have 5 methods:
def day1
end
def day2
end
def day3
end
def day4
end
def day5
end
In the views I have:
day1.html.erb
day2.html.erb
day3.html.erb
day4.html.erb
day5.html.erb
In each individual view, I have a block of code similar to this:
In day1.html.erb:
<% if current_user.speed? || current_user.admin? %>
"Display Day 1"
<% else %>
<% unless current_user.day_count.nil? %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 1 %>
"Display Day 1"
<% else %>
"This project cannot open now. Please wait until day1!"
<% end %>
<% end %>
<% end %>
In day2.html.erb:
<% if current_user.speed? || current_user.admin? %>
"Display Day 2"
<% else %>
<% unless current_user.day_count.nil? %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 2 %>
"Display Day 2"
<% else %>
"This project cannot open now. Please wait until day2!"
<% end %>
<% end %>
<% end %>
and so on, so on... until day 5.
In the routes.rb:
match 'projects/day-1' => "projects#day1", :via => [:get], as: "day1"
match 'projects/day-2' => "projects#day2", :via => [:get], as: "day2"
match 'projects/day-3' => "projects#day3", :via => [:get], as: "day3"
match 'projects/day-4' => "projects#day4", :via => [:get], as: "day4"
match 'projects/day-5' => "projects#day5", :via => [:get], as: "day5"
And in index.html.erb views I have:
<% if current_user.speed? || current_user.admin? %>
<div class="day_tracking">
<div class="day_passed"><span>✔</span><p>1</p></div>
<div class="day_passed"><span>✔</span><p>2</p></div>
<div class="day_passed"><span>✔</span><p>3</p></div>
<div class="day_passed"><span>✔</span><p>4</p></div>
<div class="day_passed"><span>✔</span><p>5</p></div>
</div>
<% else %>
<% unless current_user.day_count.nil? %>
<div class="day_tracking">
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 1 %>
<div class="day_passed"><span>✔</span><p>1</p></div>
<% else %>
<div class="day_left"><span>✘</span><p>1</p></div>
<% end %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 2 %>
<div class="day_passed"><span>✔</span><p>2</p></div>
<% else %>
<div class="day_left"><span>✘</span><p>2</p></div>
<% end %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 3 %>
<div class="day_passed"><span>✔</span><p>3</p></div>
<% else %>
<div class="day_left"><span>✘</span><p>3</p></div>
<% end %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 4 %>
<div class="day_passed"><span>✔</span><p>4</p></div>
<% else %>
<div class="day_left"><span>✘</span><p>4</p></div>
<% end %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= 5 %>
<div class="day_passed"><span>✔</span><p>5</p></div>
<% else %>
<div class="day_left"><span>✘</span><p>5</p></div>
<% end %>
</div>
<% end %>
<% end %>
What the code does is very simple. First, I check to see if the current_user is an admin or a speed user or not. If he is, then display:
✔1 ✔2 ✔3 ✔4 ✔5
( It means he can see all the projects )
Else, If the current_user is not a speed user or an admin, then display:
✔1 ✘2 ✘3 ✘4 ✘5
( It means he can only see the number of projects
equivalent to his day_count ---- in case day_count not nil!)
For Example:
If the current_user have day_count = 1, then he can only see project 1:
✔1 ✘2 ✘3 ✘4 ✘5
If the curent_user have day_count = 2, then he can only see project 1 and 2:
✔1 ✔2 ✘3 ✘4 ✘5
... And so on, so on....
The code is simple, but quite repetitive. I know it's a bad way of coding , but still cannot figure out how to reduce it efficiently and effectively. If I have more than 30 days, the code can go on, go on to more than 2,000 lines of code and probably will make the program become slow down!
Can anyone help me fix this? Thanks in advance.
routes
match 'projects/days/(:day)' => "projects#day", :via => [:get], as: "day"
views
day.html.erb
<% if current_user.speed? || current_user.admin? %>
"Display Day #{#day}"
<% else %>
<% unless current_user.day_count.nil? %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= #day %>
"Display Day #{#day}"
<% else %>
"This project cannot open now. Please wait until day#{#day}!"
<% end %>
<% end %>
controller
def day
#total_days = 5
#day = params[:day]
end
index.html
<% if current_user.speed? || current_user.admin? %>
<div class="day_tracking">
<% #total_days.each do |day| %>
<div class="day_passed"><span>✔</span><p><%= day %></p></div>
</div>
<% else %>
<% unless current_user.day_count.nil? %>
<div class="day_tracking">
<% #total_days.each do |day| %>
<% if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= day %>
<div class="day_passed"><span>✔</span><p><%= day %></p></div>
<% else %>
<div class="day_left"><span>✘</span><p><%= day %></p></div>
<% end %>
<% end %>
</div>
<% end %>
<% end %>
You can like this. There are more refactoring point, It is just concept.
It can be easily re-factored. One of the main tenets of Ruby is the DRY principle and your design goes against it.
Change your route according to this.
match 'projects/:days' => "projects#show_project", :via => [:get]
In your controller you should have this.
def show_project
end
Transfer the business logic to the project model.
def has_access?(no_of_days)
return true if current_user.speed? || current_user.admin?
unless current_user.day_count.nil?
if (Time.now.to_date - current_user.day_count.to_date).to_i + 1 >= no_of_days
true
else
false
end
end
Now in your view its as simple as.
<% if #project.has_access?(params[:days]) %>
"Display Day #{params[:days]}"
<% else %>
"This project cannot open now. Please wait until day#{params[:days]}!"
<% end %>

Add a class to the first child in a loop using Middleman

I am creating a slider for my blog and I want to add a collection of featured items to it, The slider requires that the first child load with the class selected.
How can I do something like if first child do this else do that
Here is what I have so far:
<ul class="cd-hero-slider">
<% blog.articles.select {|a| a.data[:featured] }.each do |article| %>
<li class="selected" style="background-image: url('https://images.unsplash.com/photo-1447014421976-7fec21d26d86?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&s=c82e04e1201234889daab5427f481731')">
<div class="cd-full-width">
<h2><%= link_to article.title, article %></h2>
<p><%= article.summary(250) %></p>
<%= link_to 'Read More', article, :class => 'cd-btn' %>
</div>
</li>
<% end %>
</ul>
Use each_with_index instead of each - this will give you the object but also the position into the array, first being 0:
<% blog.articles.select {|a| a.data[:featured] }.each_with_index do |article, index| %>
<% if index == 0 %>
<li>I'm the first!</li>
<% else %>
<li>Not the first</li>
<% end %>
<% end %>

Basic Search in Ruby Sinatra ActiveRecord

I'm trying to make a basic search function for a simple product inventory app on Sinatra, but don't know how to make the controller and view to properly output all the products which have similar names to a results page.
SearchPage.erb:
<form action="/search", method="post">
<input type="text" name="product[name]">
Controller:
post '/search' do
#Products = Product.find_by(name: params[:product][:name])
#Products = Product.all(:name.like => "%#{params[:name]}%") #found this on another question
erb :"result"
end
Result.erb
<% #Products.each do |product| %>
<%=product.name %>
<%=product.details %>
EDIT: I was able to make search work based on the suggestion with the following code. Thanks!:
Search.erb View
<form action="/search", method="get">
<input type="text" name="search">
Controller
get '/search' do
#products = Product.all
if params[:search]
#products = Product.search(params[:search])
else
#products = Product.all
end
erb :'results'
end
Model
class Product < ActiveRecord::Base
def self.search(search)
where("name like ?", "%#{search}%")
end
Results.erb View
<% if #products.present? %>
<table>
<td>Product Name</td><td>Company</td>
<% #products.each do |product| %>
<tr><td><%=h product.name %> </td>
<td><%=h product.company.name %></td>
<% end %>
<% else %>
<p>There are no Products containing the term(s) <%= params[:search] %>.</p>
<% end %>
</table>
I notice off the bat you're using a POST method. There is an easier way to do create search functionality for your products. Try this:
Posts Controller:
#products = Product.all
if params[:search]
#products = Product.search(params[:search]).order("created_at DESC")
else
#products = Product.all.order('created_at DESC')
end
end
Posts Model (note: If you are using SQLite keep it as LIKE. If you are using Postgres, change LIKE to ILIKE)
def self.search(search)
where('name like :pat or content like :pat', :pat => "%#{search}%")
end
Search Form (Put into your Result.erb and edit as needed but keep as get method. I personally like using form helpers but you can create a normal form if you'd like)
<%= form_tag(products_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search Posts" %>
<%= submit_tag "Search" %>
<% end %>
Render Results
<% if #products.present? %>
<%= render #products %>
<% else %>
<p>There are no posts containing the term(s) <%= params[:search] %>.</p>
<% end %>
Let me know if this works for you. If not, i'll try help some more.

group_by posts by day and then date with different div

I have the following in my index action of posts controller:
#posts = Post.all.order("created_at DESC")
In my view like:
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I want to group the posts by day and then the date like the following:
Tuesday (date)
Sports
World
Politics
Monday (date)
Sports
Catering
I just want to have the day and date in separate div's:
(<div>
<%= day %>
</div>
<div>
<%= date %>
</div>)
I am using PostgreSQL.
UPDATE
create.js.erb
$("#post_table").html("<%= escape_javascript(render('posts/post')) %>")
$modal.modal("hide");
posts_controller:
before_action :all_posts, only: [:index, :new, :create]
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
respond_to do |format|
if #post.save
format.html { redirect_to root_path }
format.js
flash[:notice] = "Successfully created post."
else
format.html { render action: 'new' }
format.js
end
end
end
private
def all_posts
#posts = Post.all.order("created_at DESC")
#post_groups=#posts.group_by{|post| [post.created_at.wday,post.created_at.to_date]}
end
index.html.erb
<% #post_groups.each do |group,posts| %>
<% day = group[1].strftime("%A") %>
<% date = group[1].strftime("#{group[1].day.ordinalize}" " %B " " %Y") %>
<div class="sort_by_date">
<span class="sort_by_post_day">
<%= day %>
</span>
<span class="sort_by_post_ordinals">
<%= date %>
</span>
</div>
<div id="post_table">
<%= render 'post', posts: #posts %>
</div>
<% end %>
Update is working fine, but whenever create a new post the refresh part is not working. it refresh but I could see the new post after I reload my website.
Thanks
controller
#post_groups=Post.order('created_at DESC').group_by{|post| [post.created_at.wday,post.created_at.to_date]}
View
<% #post_groups.each do |group,posts| %>
<%day=group[1].strftime("%A")%>
<%date=group[1].to_s%>
<div>
<%=day%>
</div>
<div>
<%=date%>
</div>
<br>
<%posts.each do |post|%>
<div><%=post.title%></div>
<%end%>
<hr>
<% end %>
In here I grouped all the posts by weekday and then group them with date.
This will return the hash of all the grouped data. hash key will be an array of format
[weekday,date] and value for this key will be an array of Posts which comes to this group and i am showing them in view according.
You can fiddle around view to change the styling according to your requirement.

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 %>

Resources