Rails - Execute actions on post's index page - ruby-on-rails

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.

Related

Ruby on Rails button to change the date field in the database to the current date for all products in the shopping list

A user can have multiple lists and a list can have multiple products
A product has a name and a date of last purchase
I am trying to add a button for each shopping list which on click it should update the last_purchase date with the current date for all the specific products added to the list already
This is what i have now
index.html.erb(in the list view folder) {each list has this button}
<%= button_to "Just-Shopped", just_shopped_product_path(...), :method => :put %>
routes.rb
resources :products do
member do
put 'just_shopped'
end
end
I know i am meant to create a function in the controller of list, but I am not sure how to select all products from the list ignoring the not selected ones and then updating that last_purchased field with the current date
This is a picture of how the rails console behaves when displaying products of a list
You're on the right track - first of all it looks like you want the button to apply to a list's products rather than an individual product, so let's change the route to:
resources :lists do
member do
put 'just_shopped'
end
end
end
Then in our lists_controller:
class ListsController < ApplicationController
...
def just shopped
list = List.find(params[:id])
list.products.each do |product|
product.update_attributes(last_purchased: DateTime.now)
end
end
That's our route and controller action setup, now we just need to add the correct button. I'm assuming you've got a #lists variable (or current_user.lists or something like that), and you're iterating through them as such:
<% #lists.each do |list| %>
<%# whatever html you want for each list %>
<%= button_to "Just-Shopped", just_shopped_list_path(list), :method => :put %>
end
You'll also need to figure out where you want to redirect to after you've updated the products in your controller

How do I use a button to update the order of a filtered category?

I am new to Rails, but slowly making progress. I can't quite wrap my head around how to achieve my next task.
I have a controller (IdeasController) with an index that looks like this:
def index
if params[:round].blank? && params[:challenge].blank?
#ideas = Idea.all.order(params[:sort])
# #ideas = Idea.all.order(created_at: :desc, cached_votes_up: :desc)
end
if params[:round].present?
#round_id = Round.find_by(name: params[:round]).id
#ideas = Idea.where(round_id: #round_id).order("created_at DESC")
end
if params[:challenge].present?
#challenge_id = Challenge.find_by(name: params[:challenge]).id
#ideas = Idea.where(challenge_id: #challenge_id).order("created_at DESC")
end
end
I am updating the view and filtering by category with the above :round and :challenge with the code below in my index.html.erb:
<%= link_to "All", ideas_path %>
<% Round.all.each do |round| %>
<%= link_to round.name, ideas_path(round: round.name) %>
<% end %>
<% Challenge.all.each do |challenge| %>
<%= link_to challenge.name, ideas_path(challenge: challenge.name) %>
<% end %>
Now, my problem is that I want to create a button that orders by created_at DESC or ASC. I want the button to essentially be a toggle. I also want another button to order by cached_weighted_average DESC or ASC. This is from acts_as_votable so I can sort by vote counts.
The problem I am running into is that I can create a link or button that orders by created_at or cached_weighted_average, but it replaces all of the URL that was previously filtered by :round or :challenge. For example, if a user clicks "Round 1" and sees all ideas marked for "Round 1" and then they click the link to order by cached_weighted_average, the URL replaces:
/ideas?round=Round+1
With this:
/ideas?sort=cached_weighted_average+ASC
What I want is:
/ideas?round=Round+1&?sort=cached_weighted_average+ASC
I know this is a very new question, but everything I have tried has failed so far. It feels like I am missing something very easy. What I noticed I can do easily is inside the controller I can do something like:
if params[:round].present?
#round_id = Round.find_by(name: params[:round]).id
#ideas = Idea.where(round_id: #round_id).order("cached_weighted_average DESC")
end
Which is perfect. This button just needs to switch between cached_weighted_average DESC and created_at DESC.
Any help is appreciated, thanks.
passing multiple parameters is one way to handle:
<%= link_to object.name, object_path(first: something, second: something_else) %>
then alter your conditionals to contemplate presence of multiple params.
to differentiate between round and challenge when attempting to allow the user to choose how they'd like to sort you could use the same name and then pass it different values.
something like:
params["round_or_challenge"]
this would change your conditional to something like:
if params["round_or_challenge"] == "round" && params["asc_or_desc"] == "asc"
# query
elsif params["round_or_challenge"] == "challenge"
# query
end
or whatever. it's basically the same...just pass the values you need. you can also pass the existing parameters from the view the same way you access them in the controller.
Thanks for the response, #toddmetheny. I didn't implement your solution, but your solution helped me understand passing multiple parameters a bit more.
I ended up creating a helper, sortable. I also used the url_for to append at the end of whatever the current URL might be. I liked this approach because it meant I could sort on any parameter. I'm not sure that it's the best solution, but it works.
def sortable (name, sort)
link_to name, url_for(params.merge(sort: sort))
end

Using Thumbs_up to display users who voted on a post

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

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.

how to separate numerous hashtags onto a separate page of a user post?

On my website, I allow users to make a post
This is what the current Post create controller looks like
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Posted!"
redirect_to home_path
else
#feed_items = []
render 'static_pages/home'
end
end
I would like to create a new page called "browse" and I want to list all of the hashtags in descending order. These hashtags will be pulled from the above posts. What is the best way to pull the hashtags (could be 1 or 2+ hashtags used in a single post) and display them in this new browse page?
You can use a regular expression to pull hashtags out of text. There's a thread here: Best HashTag Regex That post is about .NET, but regular expressions are pretty universal, so you should be able to use something there. (I recommend Rubular for testing regular expressions). This one seems popular:
hashtag_regex = /\b#\w\w+/
Now, you have a choice about when you pull the hashtags out in this way:
Option One
You can pull them out 'in real time', when the user loads the Browse page. This will probably be simpler to code, but is less flexible - you probably wouldn't be able to do things like search for posts by hashtag, or count the number of appearances of a particular hashtag. In this case, you can extract the hashtags in the view rendered by the Browse page, for instance, something like this:
<% #posts.each do |post| %>
Text: <%= post.text %>. Hashtags: <%= post.text.scan(hashtag_regex).join(',') %>
<% end %>
Option Two
You can extract hashtags when the Post is created/edited, and store them, either in a new field on the Post model, or in an associated model (Post has_many :hashtags), something like this:
def create
#post = current_user.posts.build(params[:post])
#post.hashtags = #post.text.scan(hashtag_regex)
Or as a callback on the post model:
class Post < AR:B
before_save :extract_hashtags
def extract_hashtags
hashtags = text.scan(hashtag_regex)
end
end
Then simply display them:
<% #posts.each do |post| %>
Text: <%= post.text %>. Hashtags: <%= post.hashtags %>
<% end %>
This approach is probably slightly more efficient, and by placing the hashtags in your database in their own field or table, you'll have the ability to sort by them, search for them, or count them.
I hope this is helpful.

Resources