Rails Model Data transformation - ruby-on-rails

I'm a total newbie to rails, and want to stop making the same tedious reports in excel and create a marketing analytics dashboard.
I have a User model, with created_at, marketing_source, purchases, and revenue.
What I want to do in sql is
select marketing_source, weekofyear(created_at), count(id), sum(revenue)
from User
where weekofyear(created_at) between # and #
group by marketing_source, weekofyear(created_at)
and then print this as a table to my page.
I'm just not exactly sure where and how to do the transformation. Do I put this via
sql.execute
in the controller code? Should I create a rake task to make a csv and then use javascript to read the csv and print out the table?
Any direction would be extremely appreciated.

Welcome to rails
If you are new to rails check out railscasts.com and http://guides.rubyonrails.org/
In rails you don't have to write sql statements like this.
I am assuming you have done the database migrations and have all the necessary columns in you database
in your users_controller, I think this would do what you want.
def index
#users = User.where
(["created_at >= ? AND created_at <= ?", yesterday.beginning_of_day, yesterday.end_of_day]).
group("marketing_source")
end
Then in your corresponding view
/views/users/index.html.erb
<table>
<tr>
<th>Name</th>
<th>revenue</th>
<th>Marketing source</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%=h user.name %></td>
<td><%=h user.revenue %></td>
<td><%=h user.marketing_source %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>

Related

Rails link_to not working correctly

I am trying to put in a link_to on my table to go to the show action but it is putting the URL as /admin/vulnerabilities.object_id instead of /admin/vulnerabilities/object_id
my index view is:
...
<% #vulnerabilities.each do |vulnerability| %>
<tr>
<td><%=link_to vulnerability.id, admin_vulnerabilities_path(vulnerability) %></td>
<td><%= vulnerability.type %></td>
<td><%=h truncate(vulnerability.description, :length => 80) %></td>
<td><%= vulnerability.published %></td>
<td><%= vulnerability.modified %></td>
<td><%= link_to vulnerability.href, vulnerability.href , target: :_blank %></td>
</tr>
<% end %>
...
I have a show.html.erb template setup and my show action is as follows:
def show
#vulnerabilities = Vulnerability.find(params[:id])
end
From what I can see, this should work but when clicking the links it just redirects to the index page, effectively refreshing it and not using my show page at all.
It would be helpful if you added the relevant parts of your routes.rb file to your question, but I speculate that the problem is that admin_vulnerabilities_path(vulnerability) should be admin_vulnerability_path(vulnerability).
Also, as noted in the comments, it is probably better to use #vulnerability as your instance name since find will return a single record.

Rails 4 How to make a page display a user's list of dogs

I have been practicing working on this rails application where I want to allow registered users to put up profiles of their dogs. But I just can't get the My Dogs page to display dogs that belong only to the current logged in user.
I already have the dog and user models linked via Active Record (User has_many :dogs, Dog belongs_to :user) but I don't know what to type in my dogmenu view to display only dogs that belong to the current logged in user. This is what I have so far:
views\access\dogmenu.html.erb <-- Notice that the page that will display the dogs for the current logged in user is located in the view of another controller.
<div id="dogdisplay">
<table>
<tr>
<th>Dog Name</th>
<th>Breed</th>
</tr>
<% Dog.all.each do |d| %>
<tr>
<td><%= link_to d.dname, d %></td>
<td><%= d.breed %></td>
<td><%= link_to "Edit", edit_dog_path(d) %></td>
<td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>
Thank you.
You will need two things to make this work:
A User object for the logged in user
Filter the dog list based on that id
1. Current User
This is pretty straightforward, you should be able to find this with a little googling. The big question is whether you've implemented your own user management, or you're using something like Devise to manage that.
If it's Devise, take a look at Rails Devise: get object of the currently logged in user?
If you wrote your own, you could take a look at how Devise or other user management gems provide access to the current user object. I'll leave that up to you because it seems beyond the scope of your question
2. Filter the dog list
This is pretty simple, you've got a few options:
From the view
current_user.dogs.each do |d|
Dog.where(user: current_user).each do |d|
Dog.where(user_id: current_user.id).each do |d|
From the controller
What #Sean Huber suggested is cleaner - use any of my methods above, but from the controller. E.g.
#dogs = current_user.dogs
In short, only take the dogs that have the user id matching the current user's.
I would suggest you set an instance variable in your controller action for the current user's dogs. Something like this:
def dogmenu
# this assumes you have a current_user already defined
#dogs = current_user.dogs
end
Then switch your view to use the instance variable #dogs:
<div id="dogdisplay">
<table>
<tr>
<th>Dog Name</th>
<th>Breed</th>
</tr>
<% #dogs.each do |d| %>
<tr>
<td><%= link_to d.dname, d %></td>
<td><%= d.breed %></td>
<td><%= link_to "Edit", edit_dog_path(d) %></td>
<td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>
You need to retrieve the dogs related to the current user. Since these are the user's dogs, the logic should reside in the UsersController:
In _controller/users_controller.rb_
def your_method_name
#user = User.find(current_user.id)
#dogs = #user.dogs
render :dogmenu
end
Then in views/users/dogmenu.html.erb
<div id="dogdisplay">
<table>
<tr>
<th>Dog Name</th>
<th>Breed</th>
</tr>
<% #dogs.each do |d| %>
<tr>
<td><%= link_to d.dname, d %></td>
<td><%= d.breed %></td>
<td><%= link_to "Edit", edit_dog_path(d) %></td>
<td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>
These are user dogs so the view really belongs in the users folder.
To get current user dogs, you can use object current_user
Change this
Controller
def dogmenu
#dogs = current_user.dogs
end
View
<% #dogs.each do |d| %>
To make current_user can execute in view put a helper method.
class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
#current_user ||= User.find_by_id(session[:user])
end
end
Finally you can use current_user in your view or helper
<% current_user.dogs.each do |d| %>
<tr>
<td><%= link_to d.dname, d %></td>
<td><%= d.breed %></td>
<td><%= link_to "Edit", edit_dog_path(d) %></td>
<td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
It's good for trying the first one where you're using instance variable. Hopefully it can help.

Alphabetically paginate words in Ruby on Rails

I am building a rails dictionary application. I have defined and created my whole dictionary in a simple table that draws from a .txt document via a buffer where the view looks like this:
<% #words.each do |word| %>
<tr>
<td><%= word.word %></td>
<td><%= word.wordtype %></td>
<td><%= word.description %></td>
<td><%= link_to 'Show', word %></td>
</tr>
<% end %>
Controller:
def index
#words = Word.all
end
How do I go about adding an alphabetical index at the top of the page that will display only the words for that letter? I am new to rails and ruby so any help is appreciated.
The alphabetical_paginate gem helps you implement this.
If you wish to not use a gem, this answer has some tips that you can borrow.

Compute multiple distinct averages

I'm fairly new to rails, and am still getting used to putting together methods. I'm currently trying to create a method that averages distinct data from multiple columns. I'd like to do it all in one method so that I can display the information easily in an html table.
Currently I have this in my model:
def averagedonate
scores.group(:donatedate).average('donateamount')
scores.group(:donatedate).average('rating')
end
I'd like to be able to use them in a table like this:
<% #averagedonate.each do |donatedate, donateamount, rating| %>
<tr>
<td><%= donatedate %></td>
<td><%= donateamount %></td>
<td><%= rating %></td>
</tr>
How do I change my averagedonate method to do this? Thanks in advance!
I haven't tested, but something to this effect should work
def averagedonate
scores.select("
AVG(donateamount) as avg_donateamount,
AVG(rating) as avg_rating,
donatedate
")
.group(:donatedate)
end
Then use it like this
<% #averagedonate.each do |item| %>
<tr>
<td><%= item.donatedate %></td>
<td><%= item.avg_donateamount %></td>
<td><%= item.avg_rating %></td>
</tr>
<% end %>

Returning data from database to another page in rails

How can I return data from the database on another page?
I can file this under: views / posts / index.htm.erb
<h1>Listing posts</h1>
<table>
<tr>
<th>Titulo</th>
<th>Conteudo</th>
<th>Categoria</th>
<th>Criado em</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.titulo %></td>
<td><%= post.conteudo %></td>
<td><%= post.category.name %></td>
<td><%= post.created_at.strftime("%d/%m/%Y") %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Delete', post, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Post', new_post_path %>
And I wanted to display these values ​​on another page: views / home / blog.html.erb
How do I do this? Could you explain all the steps so that I can display these values ​​in my other page.
Thanks Kocur4d
but how do I get only some information? eg: I would like that to appear in the title of the post page like this way (in blog.html.erb):
<div class="post-title">
<h2 class="title"> <a href="link_to_post"> **<% = post.titulo%>** </ a> </ h2>
</ div>
Step 1. Create controller
In your app root directory run:
rails g controller home blog
Modify controllers/homes_controller.rb :
class HomesController < ApplicationController
def blog
#posts = Post.all
end
end
Your controllers/posts_controller.rb should be already set up. Minimum what you need for your question is to have index method defined you might have other methods as well:
class PostsController < ApplicationController
def index
#posts = Post.all
end
end
Step 2. Extract Partial
change views/posts/index.htm.erb :
<h1>Listing posts</h1>
<%= render partial: 'shared/posts', object: #posts %>
<%= link_to 'New Post', new_post_path %>
create/modify views/home/blog.html.erb :
<h1>Listing posts</h1>
<%= render partial: 'shared/posts', object: #posts %>
<%= link_to 'New Post', new_post_path %>
create views/shared/_posts.html.erb :
<table>
<tr>
<th>Titulo</th>
<th>Conteudo</th>
<th>Categoria</th>
<th>Criado em</th>
<th></th>
<th></th>
<th></th>
</tr>
<% posts.each do |post| %>
<tr>
<td><%= post.titulo %></td>
<td><%= post.conteudo %></td>
<td><%= post.category.name %></td>
<td><%= post.created_at.strftime("%d/%m/%Y") %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Delete', post, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
Step 3. Set up routes.
You should have something like this in your routes.rb file:
resources :posts or match 'posts/index' => 'posts#index'
add this to config/routes.rb:
match 'home/blog' => 'home#blog'
so it might look like this(there is few variants):
config/routes.rb:
YourAppName::Application.routes.draw do
root to: 'posts#index'
resources :posts
match 'home/blog' => 'home#blog'
end
Now when you start rails server(assuming standard configuration) and visit:
127.0.0.1:3000/posts/index and 127.0.0.1:3000/home/blog
you should see same content.
This should work copy-and-paste but I could make some typos and other small mistakes(hope not, if ill find any ill try to edit them asap). In general look at it as you need 3 steps to forward http request down your rails application stack.
Map url to controllers using routes.
Create controllers and inside prepare data for views.
Display data in Views.
Look around in Rails Guides, Rails for Zombies and Rails Tutorial for more info.
---------Upadate to your second question-----------
I don't really understand what would you like to achieve?? At the moment both index.html.erb and blog.html.erb showing the same data, that was what you ware asking for?
post representing one post and is available in sharde/_posts.html.erb. You can't reference it from index.html.erb or blog.html.erb.
#posts represents all the posts and its available in index.html.erb or blog.html.erb.
render partial: 'shared/posts', object: #posts -- this line say "Hey man! Paste here content of shared/posts file, and btw I have here a local variable #posts so if you need to use that date in shared/posts file Ill name it posts from in side there"
To make them look different modify both files and part that will be identical for both of them is in a sharde/_posts.html.erb.
Try for example remove this line:
<td><%= post.category.name %></td>
from shared file to see what is going to happen.
Add some html tags and thinker with it.
Rails has may helper methods available' to find out about them check the links I give you and google, google, google.
Try to add some links with link_to helper
In your home controller, for the blog method, set #posts as you need...
Maybe
#posts = Post.all

Resources