I'm using the thumbs_up gem in my application and I'm trying to figure out the best way to save votes in my controller while iterating.
Here is my model:
class Vendor < ActiveRecord::Base
has_many :inventory_items
has_many :items, through: :inventory_items
has_many :shopping_lists, through: :inventory_items
acts_as_voteable
end
my current controller:
def vote_for_vendor
# not sure what to put in here
end
def vote_against_vendor
# not sure what to put in here
end
my current view:
<% provide(:title, 'Stores') %>
<table class="table table-condensed table-hover">
<tr>
<th>Name</th>
<th>Address</th>
<th>Favorite?</th>
</tr>
<% #vendors.each do |v| %>
<tr>
<td><%= v.name %></td>
<td><%= v.address %></td>
<td>
<% if current_user.voted_for(v) %>
<%= link_to 'unlike', vote_against_vendor_vendors_path(vendor_id: v.id), :remote => true %>
<% else %>
<%= link_to 'like', vote_for_vendor_vendors_path(vendor_id: v.id), :remote => true %>
<% end %>
</td>
</tr>
</table>
Most of the examples I've seen have used params([]) to pass the relevant information to the controller. I don't really have params because this is just my index page that shows all vendors. How can I save votes using this gem while iterating? Thanks in advance!
Updated Controller w/ help from MrYoshi
class VendorsController < ApplicationController
def index
#vendors = Vendor.all
end
def vote_for_vendor
vendor = Vendor.find(params[:vendor_id])
current_user.vote_for(vendor)
respond_to do |format|
format.js
end
end
def vote_against_vendor
vendor = Vendor.find(params[:vendor_id])
current_user.vote_against(vendor)
respond_to do |format|
format.js
end
end
end
my routes:
resources :vendors do
collection { post :vote_for_vendor }
collection { post :vote_agaist_vendor }
end
Current Server Error
Started GET "/vendors/vote_for_vendor?vendor_id=4" for 127.0.0.1 at 2013-09-06 10:07:29 -0700
AbstractController::ActionNotFound (The action 'show' could not be found for VendorsController):
...........
Rendered /Users/#Myname/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb within rescues/layout (0.5ms)
I give you the start of what you want, and you will be able to do the rest by yourself I think:
View:
<% if current_user.voted_for(v) %>
<%= link_to 'unlike', vote_against_vendor_vendors_path(vendor_id: v.id), :remote => true %>
<% else %>
<%= link_to 'like', vote_for_vendor_vendors_path(vendor_id: v.id), :remote => true %>
<% end %>
Controller:
def vote_for_vendor
vendor = Vendor.find(params[:vendor_id])
current_user.vote_for(vendor)
render :nothing => true
end
And the vote_against is pretty simple to guess now that you have this one above ;)
For your 'current server error' (AbstractController::ActionNotFound (The action 'show' could not be found for VendorsController):), you need to add a member route to your config/routes.rb file, like this:
resources :vendors do
member do
post 'vote_for_vendor'
post 'vote_against_vendor'
end
end
You are currently using collection routes which are for resources that don't need a particular ID to work. I highly recommend reading the Rails Guide on routes:
Rails Guide Documentation on Routes
Related
I have users that have posts.
<p id="notice"><%= notice %></p>
<h1>Listing Posts</h1>
<table>
<thead>
<tr>
<th>Comment</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_user_post_path %>
And in controller
def destroy
#user = #post.user
#post.destroy
respond_to do |format|
format.html { redirect_to user_posts_url(#user), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
What's the proper way to implement a link and controller action to destroy all posts for a particular user?
Edit:
config/routes.rb
resources :users do
resources :posts, shallow: true
end
Edit 2:
resources :users do
#resources :posts, shallow: true
resources :posts, shallow: true do
delete :destroy_all, on: collection
end
end
gives no block given (yield) error
aww my bad.. Just found the error.. forgot to add : to collection
I would pass an array of post IDs only if selected posts need to be deleted. If you want to delete all posts for a particular user, then here's how I would approach it:
config/routes.rb
resources :users do
resources :posts do
delete :destroy_all, on: :collection
end
end
Here, on: :collection means that the route applies to the collection of posts; the route therefore looks like this:
/users/:user_id/posts/destroy_all
You can read more about adding member and collection routes in the Rails Guides:
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
app/controllers/posts_controller.rb
def destroy_all
user = User.find(params[:user_id])
user.posts.destroy_all
# redirect somewhere
end
app/views/posts/index.html.erb
<%= link_to(
"Delete all posts!",
destroy_all_user_posts_path,
method: :delete
) %>
If you want to delete all posts for the current_user, modify like so:
config/routes.rb
resources :posts do
delete :destroy_all, on: :collection
end
app/controllers/posts_controller.rb
def destroy_all
current_user.posts.destroy_all
# redirect somewhere
end
app/views/posts/index.html.erb
<%= link_to(
"Delete all posts!",
destroy_all_posts_path,
method: :delete
) %>
Hope that helps.
I would create a separate controller method that accepts an array of post ids.
posts_controller.rb
def destroy_all
posts = Post.where(:id => params[:post_ids])
posts.delete_all
redirect_to :back
end
You will also need to supply the ids to the view method.
posts_controller.rb
def index
...
#posts_ids = Post.find(... how ever you need to select all posts...).pluck(:id)
...
end
views/posts/index.html.erb
...
<%= link_to destroy_all_posts_path(:post_ids => #posts_ids), :method => :destroy %>
...
You will also need to supply the route.
routes.rb
resources :users do
resources :posts
delete :destroy_all
end
end
And that should be it :)
You can use:
def destory_posts(user)
user.posts.destroy_all
render :nothing => true
end
add this method to your routes file.
Create a link like destory_posts_path(current_user) from where you want to delete the posts.
i'm a beginner in ruby on rails and getting an error i seem not to understand.
under the profile page for the Tradesman, i am trying to call all trades and all listed jobs under the trade. Trade has_many jobs & jobs has_many trades.
TrademanprofilesController:
class TrademanprofilesController < ApplicationController
def show
#user = current_user
end
def jobleads
end
def purchased
end
def memberBenifits
end
def account
end
def editjoblead
#trades = Trade.order(:name)
#jobs = Job.all
if params[:search].present?
#applications = Application.near(params[:search], 100, order: 'distance')
#hash = Gmaps4rails.build_markers(#applications) do |application, marker|
marker.lat application.latitude
marker.lng application.longitude
marker.infowindow application.location
marker.infowindow application.trade.name
end
else
#applications = Application.all
end
#applications_trades = #applications.group_by { |t| t.trade_id } end end
The views page which is a partial being called elsewhere. _trademanprofile_skills.html.erb:
<table>
<thead>
<tr>
<th>Name</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #trades.each do |trade| %>
<tr>
<td>
<%= trade.name %></br>
<ul><% #trade.jobs.each do |job| %></ul>
<li><%= job.name %></li>
<% end %>
</td>
<td><%= link_to 'Show', trade %></td>
</tr>
<% end %>
</tbody>
</table>
model: Trade.rb
class Trade < ActiveRecord::Base
attr_accessible :name, :job_ids
has_many :applications
has_many :jobs, through: :applications
end
model: Job.rb
class Job < ActiveRecord::Base
attr_accessible :name, :trade_ids
has_many :applications
has_many :trades, through: :applications
end
The error i get:
NoMethodError in Trademanprofiles#editjoblead
undefined method `jobs' for nil:NilClass
and highlights this line:
<ul><% #trade.jobs.each do |job| %></ul>
<li><%= job.name %></li>
<% end %>
i tried the below but did not work
<% #trades.each do |trade| %>
<%= trade.name %>
<%= trade.jobs %>
<% end %>
i got this displayed:
#<Job::ActiveRecord_Associations_CollectionProxy:0x00000106b0f1d8>
i also tried the below but did not work
<% #trades.each do |trade| %>
<%= trade.name %>
<%= trade.job_ids %>
<% end %>
but it only returned the id numbers of the jobs under the trade Aerial / Network
Aerial / Network Specialist
[978, 979, 980, 1039, 1040, 1041]
my routes file:
Rails.application.routes.draw do
resources :images
devise_for :users
resources :jobstartdates
resources :budgets
resources :applications do
collection do
get :search
get :search_result
get :business_details
end
end
get 'home/index'
resources :trades
resources :jobs
root to: 'home#index', as: 'home'
resource :trademanprofiles do
get :show
get :jobleads
get :purchased
get :memberBenifits
get :account
get :editjoblead
end
resources :employeenumbers
resources :businesstypes
resources :trademanroles
resources :titles
resources :adverts
resources :distances
i would like the Trade name & the Job names (not the ids) to be displayed. Many thanks an i truly apologise if this is a simple question.
If you look at your method
def editjoblead
#trades = Trade.order(:name) #this will return a collection of trades to you
#jobs = Job.all
#other logic
end
and in your view you have this
<ul>
<% #trade.jobs.each do |job| %></ul>
<li><%= job.name %></li>
<% end %>
First of all you need to correct your html you have closed ul and then using li and secondly you are trying to get a collection on a collection(#trade is a collection and jobs will give you a collection)
You need to do this:
<% #trades.each do |trade| %>
// this will give a single trade present in #trades
<tr>
<td>
<%= trade.name %></br>
<ul>
<% trade.jobs.each do |job| %>
// this will give a job associated with your trade, notice it's trade and not #trade
<li><%= job.name %></li>
<% end %>
</ul>
</td>
<td><%= link_to 'Show', trade %></td>
</tr>
<% end %>
what about your routes.rb file? I thing the error may be in there put like this in your route file
resources :trades do
resources :applications
resources :jobs
end
I am making a simple app where a user can create a Series and then an episode to the series, and then multiple links to each episode. I tried using the gem Cocoon but I wasn't able to get it to show up on the view.
I thought I had set everything right, but I hope someone can help me find what I am doing wrong or missing, thanks!
I am getting this error:
param is missing or the value is empty: series
And in the console:
Processing by SeriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KAF06O/2C3EBRwos7UnJGSzWF2SGVVB7YdrNnuWt0M=", "commit"=>"Update Series", "id"=>"2"}
Series Load (0.2ms) SELECT "series".* FROM "series" WHERE "series"."id" = ? LIMIT 1 [["id", "2"]]
Completed 400 Bad Request in 39ms
ActionController::ParameterMissing (param is missing or the value is empty: series):
app/controllers/series_controller.rb:64:in `series_params'
app/controllers/series_controller.rb:35:in `block in update'
app/controllers/series_controller.rb:34:in `update'
These are what my models look like:
# app/models/series.rb
class Series < ActiveRecord::Base
has_many :episodes
accepts_nested_attributes_for :episodes
end
# app/models/episode.rb
class Episode < ActiveRecord::Base
belongs_to :series
has_many :links
accepts_nested_attributes_for :links
end
# app/models/link.rb
class Link < ActiveRecord::Base
belongs_to :episode
end
My controller:
class SeriesController < ApplicationController
before_action :set_series, only: [:show, :edit, :update, :destroy, :links]
def new
#series = Series.new
#series.episodes.build
end
def update
respond_to do |format|
if #series.update(series_params)
format.html { redirect_to #series, notice: 'Series was successfully updated.' }
format.json { render :show, status: :ok, location: #series }
else
format.html { render :edit }
format.json { render json: #series.errors, status: :unprocessable_entity }
end
end
end
# ... ignoring content that hasn't changed from scaffold
def links
#episodes = #series.episodes
end
private
def series_params
params.require(:series).permit(:name,
episodes_attributes: [:id, :title,
links_attributes: [:id, :url]
])
end
end
The views files:
<!-- app/views/series/links.html.erb -->
<h1><%= #series.name %></h1>
<%= form_for(#series) do |f| %>
<table>
<thead>
<tr>
<td>Title</td>
<td>Season</td>
<td>Episode</td>
</tr>
</thead>
<tbody>
<% #episodes.each do |episode| %>
<tr>
<td><%= episode.title %></td>
<td><%= episode.season %></td>
<td><%= episode.episode %></td>
<td>
<%= f.fields_for :episodes, episode.build do |e| %>
<%= e.fields_for :links, episode.link.build do |a| %>
<%= a.text_area :url %>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And the routes file:
MyApp::Application.routes.draw do
resources :series do
member do
get 'links'
end
end
end
I think series parameter is not passing from your view
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KAF06O/2C3EBRwos7UnJGSzWF2SGVVB7YdrNnuWt0M=", "commit"=>"Update Series", "id"=>"2"}
in your action you are using series_params method in that you are using like params.require(:series).permit .
so it's throwing param is missing or the value is empty: series
please check in you view file you passing the view or not
You need to build your links too:
#app/controllers/series_controller.rb
def new
#series = Series.new
#series.episodes.build.links.build #-> creates one link object you can populate
end
Then you need to change your form to use the built link objects:
<%= f.fields_for :episodes do |e| %>
<%= e.fields_for :links do |a| %>
<%= a.text_area :url %>
<% end %>
<% end %>
This should get the new & create actions working. However, you posted the log for the update action -- are you having issues with create or update?
I'm making a twitter-copy and right now I'm trying to show all the posts from the users an other user is following. I'm new at ruby and rails, so i might be doing this a really weird way..
These are the files I have:
session#home.html.erb
<h2 class='User_Header'> Home <h2>
<%= link_to "New Post", controller: "posts", action: "new" %>
<%= link_to "Log Out", :controller => "sessions", :action => "logout" %>
<%= show_tweets("following") %>
sessions_helper
module SessionsHelper
def show_tweets(opt)
if opt == "following"
#sub = Subscription.where("userID = ?", #current_user.id)
#post = Post.where("user_id = ?", #sub.followingID)
render partial: 'shared/follower_tweets'
end
end
def show_tweet(s)
#post = Post.where("user_id = ?", s.id)
render partial: 'shared/tweet'
end
def tweet_username(p)
#username = User.where("id = ?", p.user_id)
Rails.logger.debug #username.inspect
render partial: 'shared/user'
end
end
_follower_tweets.html.erb
<h2>Tweets</h2>
<table>
<tr>
<th>Username</th>
<th>Tweet</th>
</tr>
<% div_for(#post, class: 'post') do %>
<td><%= tweet_username(#post) %></td>
<td><%= #post.content %></td>
<% end %>
</table>
_user.html.erb
<%= #username %>
session.rb
class Session < ActiveRecord::Base
attr_accessible :content, :user_id, :followingID, :userID
end
Error
app/views/sessions/home.html.erb where line #9 raised:
undefined method `followingID' for #<ActiveRecord::Relation:0x007fd74b66f8a8>
What is happening is that you have followingID on your Session model instead of Subscription model. Should be something like the following:
class Subscription < ActiveRecord::Base
attr_accessible :followingID
end
However, the problem is bigger than that. You must read about Active Record Associations, then you would be able to do something like
#subs = #current_user.subscriptions
#posts = #current_user.posts
check if your model's association is correct. the messages indicates that there's an error about this.
Hello I'm having 2 objects the one events and the other one categories. I want to put the categories in the layout of the events. i tried but i;m getting an error message
Showing layouts/events.html.erb where line #40 raised:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
<% for category in #categories %>
<li><%=h category.name %>
<ul>
<% for subcategory in #subcategories %>
<% if subcategory.category_id == category.id %>
<li><%=h subcategory.name %></li>
<% end %>
<% end %>
</ul>
</li>
<% end %>
events_controller
def index
#subcategories = Subcategory.find(:all, :order=>"category_id , name")
#categories = Category.find(:all)
#events = Event.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #events }
end
end
class Subcategory < ActiveRecord::Base
belongs_to:category
has_many:events
end
class Event < ActiveRecord::Base
belongs_to:subcategory
end
class Category < ActiveRecord::Base
has_many:subcategories
end
my routes
map.root :controller => 'events'
# Index
map.connect '/index/', :controller=>'events', :action=>'index'
map.connect '/index/events/', :controller=>'events', :action=>'index'
map.connect '/index/category/:id', :controller=>'events', :action=>'showallcategoryposts'
# Admin
map.connect '/admin/', :controller=>'events', :action=>'adminindex'
map.connect '/admin/events/new', :controller=>'events', :action=>'new'
map.connect '/admin/category/', :controller=>'subcategories', :action=>'index'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
I'm using Instant Rails 2.0
how i can correct my code in order to work?
Thank you
Apart from whatever problem you have... IMHO, the code looks quite compromising.
Following are the things, which shouldn't be done the way they are currently:
Building the URLs manually like href="/index/category/<%=h subcategory.id %>" But I can't say much on it to correct it without knowing which Rails version you are on and without seeing your routes.rb
Controller Code is incorrect
Model code also needs improvements
Models should look like this:
class Subcategory < ActiveRecord::Base
belongs_to :category
has_many :events, :order => "created_at desc"
end
class Event < ActiveRecord::Base
belongs_to :subcategory
end
class Category < ActiveRecord::Base
has_many :subcategories, :order => "name"
end
EventsController should be like this:
def index
#categories = Category.all(:order => "name", :include => {:subcategories => [:events]})
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #categories }
end
end
And your view should look like:
<% unless #categories.empty? %>
<% #categories.each do |category| %>
<li>
<%=h category.name %>
<ul>
<% category.subcategories.each do |subcategory| %>
<li>
<%=h subcategory.name %>
</li>
<% end %>
</ul>
</li>
<% end %>
<% else %>
Sorry, no events found!
<% end %>
I hope this code will fix your bugs as well.
Please try it.
NOTE: More improvements required in views, depending on your Rails version and your routes.rb ... you should use the path/url methods like category_path(category) etc.
You didn't post your model code. I wonder if you're taking advantage of ActiveRecord associations. If you were, you wouldn't need anything more than #events. You could do stuff like:
<% #events.each do |event| %><br/>
<% event.categories.each do |category| %>
stuff
<% end %>
<% end %>
Check out this guide.
I am pretty sure EventsController#index is rendering views/events/index.html.erb, and layouts/events.html.erb knows nothing of #categories which is set for use in said rendering. Where do you render layouts/events.html.erb? Try placing this below your class definition:
layout 'events'
Also, it is worth checking out what #categories is within the controller with a Rails.logger.debug. Is it nil there as well?