Using Thumbs_up to display users who voted on a post - ruby-on-rails

I'm using Thumbs_Up gem to let users vote on a post(called Topic). I've done the voting part but now I want to display the users who voted on that particular post. I'm very new to Ruby On Rails, and I'm stuck at the view part.
Here's my controller: app/controllers/topics_controller.rb
def vote_who
#topic = Topic.find(params[:id])
#vote_list=#topic.voters_who_voted_for
end
In my index.html.erb, I want to display the names of there users who voted on that post. This should be right next to the vote button. Kind of like this,
But how do I send back information from the controller?
Or is this approach completely wrong?

IMHO, it's more preferable to show all voters in the 'show' view of the each particular Topic (imagine you have 100 voters for one topic, what this table in index view will look like?).
This way you don't need any distinct action (due to Rails conventions 1 action == 1 view (in general)). Just put in your show action:
def show
#topic = Topic.find(params [:id])
#vote_list = #topic.voters_who_voted_for
end
Then in your view (show.html.erb) you need to do something like this:
<% #vote_list.each do |voter| %>
<%= voter.email %> #or login, or name, or any user's attribute you want to display in your list
<% end %>
Or even try to simplify this: leave show action in your TopicsController as it is (don't create any #vote_list variable, only find right Topic), and call voters_who_voted_for method inside your show view, e.g.:
<%= #topic.title %>
<%= #topic.body %>
<%= #topic.voters_who_voted_for %>

Related

Render results on #show without storing data in ActiveStorage

I'm learning RoR by building my first app (yay!). I gotta a question thought as rails guides do not cover this topic:
How to render unique results on #show to a user without storing any data in a model?
Steps I want to take:
Create a basic index view with a form_tag that will allow user to submit a link (string) and click submit button
Write Service Objects that will allow me to parse that link and create a response I want user to see
I want to write a #show method in a separate controller that will allow me to display all the data. (I also want to parse my params[:link] in that method using Service Objects.
I want to finally display this data in a table in #show view (probably I need to create a unique #show/[:id] for each user?
Here's what my app looks like at the moment (more or less):
Static Controller (just to render index.html.erb with a form)
class StaticController < ApplicationController
def index
end
end
Static Index view (yup, parsing imgur link here)
<h1>Hello Rails!</h1>
<%= form_tag("/images", method: "post") do %>
<p>
<%= label_tag(:imgur_link) %><br>
<%= text_field_tag(:imgur) %>
</p>
<p>
<%= submit_tag("Get my cards") %>
</p>
<% end %>
Images Controller (where all the magic SHOULD happen)
class ImagesController < ApplicationController
def show
#collection = params[:imgur_link]
#service1 = service1.new(*args).call
#service2 = service2.new(*args).call
...
end
end
Images Show view
Empty as I'm stuck with the Images controller at the moment.
Any help would be more than appreciated.
Thanks!
There is no reason you should put something into storage just in order to display it. If you get to a point when you have the results in your controller, you could just pass them to view in some #variable
As I see, you have set up the form for step 1. If you also have routes.rb call 'images#show' for POST /images, then you will have params[:imgur_link] available in your show action. This should do:
# config/routes.rb
YourApplication.routes.draw do
# ...
post '/images' => 'images#show'
end
Now you have to somehow process that link. Since I don't know what your results should be, I'm going to assume that you have two classes, Service1 and Service2, both of which accept an URL and return collection of results, and both collections hold the elements of the same class. Then you can leave only unique results for your show view, like this:
# app/controllers/images_controller.rb
class ImagesController < ApplicationController
def show
link = params[:imgur_link]
results1 = Service1.new(link).results
results2 = Service2.new(link).results
#results = (results1 + results2).uniq
end
end
Then you can do something with #results in your show view. E.g.
# app/views/images/show.html.erb
<% #results.each do |result| %>
<%= result.inspect %>
<% end %>

Admin-editable views

There doesn't appear to be a gem for this, and I think a CMS is overkill as the client only wants to edit the welcome message on the home page!
Here's what I think I should do:
1) Create Page model:
rails g model Page name:string
2) Create Field model:
rails g model Field name:string content:string page_id:integer
3) Create relationship, Page h1:b2 Field
4) Create rake task to set up the message field that belongs to the welcome page:
namespace :seeder do
namespace :initial_seed do
task pages: :environment do
p = Page.create(name: "Welcome")
p.fields.create(name: "welcomemessage", content: "everything goes here. The long rambling welcome!")
end
end
end
5) Create a 'static' controller for the 'static'-ish pages. The home, the about us etc...
class Static < ApplicationController
def home
#fields = Page.where().fields
end
end
6) In the view, populate the welcome message from the database (I'll create a helper for this):
<% field = #fields.find {|x| x[:name] == 'welcomemessage' } %>
<%= field.content %>
So that's the reading done. Now onto the creation, updation and deletion:
6) Create a control panel controller:
class Panel < ApplicationController
def pages
#pages = Page.all
end
end
7) Display fields in the view at panel/pages.html.erb: (I'll use partials here)
<% #pages.each do |page| %>
Title: <%= page.name %>
<% page.fields.each do |field|%>
Field: <%= field.name %>
<% form_for(field) do |f| %>
<% f.text_area :content%>
<% f.submit %>
<%= end %>
<% end %>
<% end %>
Now this is just a rough run down of what I want to do. There are a few problems I want to query, though.
Is this sort of how you would do this?
How should I configure my routes? What is a clever way of populating the #fields variable (see step 5) with the fields for the page we're viewing?
If I do have a panel/pages.html.erb view, should it simply display all of the editable fields in text areas? How should it update these areas? Multiple submit buttons inside multiple forms? What if someone wants to edit many fields at once and submit them all at once?
Where should these forms go? Should I create multiple RESTful actions all inside the Panel controller like this?:
class Panel < ApplicationController
# new and create not present as the pages have to be created manually
# Enabling the user to create their own pages with their own layouts is a bit insane
def pages
#pages = Page.all
end
def pages_update
end
def pages_destroy
end
end
Multiple restful routes in one controller doesn't strike me as organised, but it would make it easier to lock down the panel controller with a before_action hook to redirect if not admin...
Also, I'm nearing the end of a big job, and all I need to do is add the ability to edit one field on one page and them I'm done and I really don't want to have to figure out alchemy_cms or whatever. In future, yes, but, please, please, please someone give me some small pointers here.
I would strongly advise against building your own CMS. It's fraught with difficulties, and it seems like you're running up against some of those now. You should go and check out something like AlchemyCMS.

Rails - Execute actions on post's index page

I have a model "Products" (which is a child model of parent model "Assortments") which can be liked by the user. Right now, you can only like the Product on the Products Show page because i'm able to find the products ID, which is what i need to like it
def like
#assortment = Assortment.find(params[:assortment_id])
begin
current_user.vote_for(#product = Product.find(params[:id]))
respond_with #product, :location => assortment_product_path
rescue ActiveRecord::RecordInvalid
redirect_to #product
end
end
I would also like user's to be able to like the product on the products index page. For example, if you go to Pinterest, you can like all the products on their fluid grid layout page as well as on each pictures respective page.
This is one of those things I have yet to learn how to do with Rails. How can i accomplish this??
Thanks in advance! Happy Holidays
Assuming your like action is in your ProductsController, and you have set #products equal to the products you want for your index page, and you're using erb, put something like this in your view:
<% #products.each do |product| %>
<%= link_to "Like", product_link_path(id: product.id) %>
<% end %>
Even if you have it set up differently, it can't be too far off from this.

dynamic fields in the rails view

I want to show fields from the database dynamically.i.e, if suppose
in one case my #user object reads from users table
#user = User.new
in another case #user object reads from posts table
#user = Post.new
Then dynamically my view(new page) shows the fields based on the model selected.
<% for column in #object.class.column_names %>
<%= #object.send(column) %>
<% end %>
EDITED (To exclude some columns from the view)
exclude_columns = ['id', 'created_at', 'updated_at']
<% for column in #object.class.column_names
next if exclude_columns.include?(column) %>
<%= #object.send(column) %>
<% end %>
This might be more than you are asking for, but perhaps you want to have a look at the presenter pattern. This will let your view make use of one single interface while hiding away the view logic.
I think this post will give you a nice introduction to the topic: http://mikepackdev.com/blog_posts/31-exhibit-vs-presenter
I'm going to disagree with Salil. you should never do assigns in the view (ERB). If you're doing that, you need to move towards a helper or a presenter depending.
Why would you not just walk the tree? #users should, by name, return a collection of users. #user.posts would walk the relationship tree. I'm curious why you're fighting the rails default way of working. Can you share more code to help us understand?

Displaying data from multiple models on home page?

I'd like to display a summary of data from various models on my home page. There's a HomeController and a home/home.html.erb but no model. I was hoping it would be as simple as placing something like this for each model in the HomeController and then view, but nope, that doesn't work!
Controller:
def load_tracks
#tracks = Track.all
end
View:
<% #tracks.each do |track| %>
<%= track.name %> - <%= track.isrc %>
<% end %>
Any pointers would be really appreciated!
Your controller will have to look like this:
class HomeController < ApplicationController
def home
#tracks = Track.all # or this could come from a method
end
end
And your view can be the same now. When rails sees a request it looks for the action with that name. So when you tried to go to /homes/home it went in to the Homes controller to find a home action and couldn't find it, so that's probably why it didn't work.
EDIT You shouldn't really have a "HomesController" anyways. A "PagesController" might make more sense. Check out Michael Hartl's RoR tutorial book on the subject.
Let's say you have two models, Track and Playlist and you want to display information about them on the Home controller's index page. In app/view/controllers/home_controller.rb
def index
#tracks = Track.all
#playlists = Playlist.all
end
then in the view, app/view/home/index.html.erb
<h1>Tracks and Playlists R Us</h1>
<p><%= "We have #{#tracks.count} tracks and #{#playlist.count} playlists." %></p>
You migh also want to take a look at Presenter. It's a good and clean way to grab data from different models.
Here: http://railscasts.com/episodes?utf8=%E2%9C%93&search=presenter
and http://railscasts.com/episodes?utf8=%E2%9C%93&search=draper

Resources