Why my posting is taking me to wrong URL? - ruby-on-rails

When I'm posting, it takes me to
example.com/shop.:community_name
instead of
example.com/shop/:community_name
My routes.rb
resources :communities, :path => "shop", do
resources :community_topics, :path => "topic", :as => :'topic'
end
_form.html.erb
<%= form_for #community, :html => { :class => 'form-horizontal' } do |f| %>
...
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= f.submit 'Destroy',
:confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')),
:class => 'btn btn-danger', :name => 'destroy' unless #community.new_record? %>
<% end %>
update action in communities_controller.rb I use to_param that's why using community_name
def update
#community = Community.find_by_community_name(params[:id])
respond_to do |format|
if #community.update_attributes(params[:community])
format.html { redirect_to communities_path(#community.community_name), notice: 'Community was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #community.errors, status: :unprocessable_entity }
end
end
end

It should be
... redirect_to community_path(#community.community_name) ...
in the update action of your CommunitiesController.

hate named routes...
redirect_to #community

Related

Rails passing params in link_to how to make it secure

I am trying to create a like and dislike function inside rails for that I am using lin_to helper to pass params but there is an issue when ever someone tries to copy paste the links it updated the database . I am using ajax to make this function work here is the code for my method .
Controller code:
class FeedLikesController < ApplicationController
before_action :authenticate_user! ,only: [:create, :destroy]
before_action :get_feed ,only: [:create, :destroy]
def index
#fees = FeedLike.all
respond_to do |format|
format.html
format.js
end
end
def update
#feed_likes = FeedLike.find_or_create_by(feed_like_params)
respond_to do |format|
if #feed_likes.save
format.html { redirect_to root_url, notice: 'Like ' }
end
end
end
def create
#feed_like_counter = Feed.find(params[:feed_id])
#feed_likes = FeedLike.find_or_create_by(:feed_id => params[:feed_id],:user_id =>params[:user_id])
#f = #feed_like_counter.like_count
#feed_like_counter.like_count = #f+1
#feed_like_counter.save
respond_to do |format|
if #feed_likes.save
format.html { redirect_to root_url, notice: 'Like ' }
format.js
end
end
end
def delete
end
def destroy
#feed_like_counter = Feed.find(params[:feed_id])
#feed_likes = FeedLike.where(feed_like_params)
#f = #feed_like_counter.like_count
#feed_like_counter.like_count = #f-1
#feed_like_counter.save
respond_to do |format|
if #feed_likes.destroy_all
format.html { redirect_to root_url, notice: 'Unlike ' }
format.js
end
end
end
def feed_like_params
params.permit(:user_id, :feed_id)
#params[:market_place]
end
def get_feed
#feed = Feed.find(params[:feed_id])
end
end
And in views my link is like this:
<div class="feed-like-<%= #feed %> " >
<%= link_to "like",{ :action => 'create', :controller => 'feed_likes', :feed_id => #feed, :user_id => current_user.id, :remote => true }, method: :post,class: "btn btn-primary" %>
</div>
And dislike link is like this:
<div class="feed-like-<%= #feed %> " >
<%= link_to "Dislike",{ :action => 'destroy', :controller => 'feed_likes', :feed_id => #feed, :user_id => current_user.id, :remote => true }, class: "btn btn-primary" %>
</div>
And my routes is like :
get "/feed_likes/:feed_id/feed_likes/:user_id" => "feed_likes#destroy"
post "/feed_likes/:feed_id/feed_likes/:user_id" => "feed_likes#create"
Here the issue is whenever someone wants to like the feed when I passes the url direclty it updated the database how can I restrict this only when user click the button only then it update the database not by url :
There is another issue with this I am using ajax onclick event it updated the database but when I click the like button fast it update the databse 2 or 3 times before the dislike partial appear . Is there any way I can use this .
I find a solution for this question it was very easy I was trying to generate the routes not in rails way so I did some changes . First I added
resources :feed_likes
and then replace the links like this :
<%= link_to "Dislike", feed_like_path(:feed_id => #feed, :user_id => current_user.id ), :confirm => 'Are you sure?',:remote => true, :method => :delete,data: { disable_with: "Processsing..." }, class: "btn btn-primary" %>
<%= link_to "like", feed_likes_path(:feed_id => #feed, :user_id => current_user.id ), :confirm => 'Are you sure?',:remote => true, :method => :post, data: { disable_with: "Processsing..." }, class: "btn btn-primary" %>

Rails: return only json

In my app there is a list of items which you can upvote. I want to make these votes with AJAX calls.
This is the view:
<ul class="list-groups">
<% #questions.each do |question| %>
<li class="list-group-item">
<%= link_to question.description, question_path(question) %>
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, html: { class: 'form-inline' }) do |f| %>
<%= f.submit 'Up vote', class: "btn btn-default" %>
<%= f.hidden_field :id, :value => question.id %>
<% end %>
</li>
<% end %>
</ul>
And this the method that does it:
class VoteController < ApplicationController
respond_to :json
def vote
question_id = params[:question][:id]
user_id = current_user.id
vote = Vote.where(["question_id = :q", { q: question_id }]).where(["user_id = :u", { u: user_id }])
respond_to do |format|
if vote.nil?
#vote = Vote.new
#vote.question_id = question_id
#vote.user_id = user_id
#vote.save
format.html { render '/home/index' }
format.json { render :json => { :status => 'ok' } }
else
format.html { render '/home/index' }
format.json { render :json => { :status => 'failed', :msg => 'You already voted' } }
end
end
end
end
If I don't include this format.html { render '/home/index' } I am getting this error:
ActionController::UnknownFormat in VoteController#vote
But I don't want to render the page again, I am just loading the pieces of html that will change after the action with jQuery and ajax.
How can I respond only with the json?
Use respond_with instead of respond_to in your controller action.
respond_with do |format|
respond_to at the top of your controller is designed to work with respond_with in your controller action, whereas respond_to in your controller action ignores the respond_to that you've defined at the top of your controller.
Also make sure you are making a remote call, instead of a normall one if you want your request to go through AJAX.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, remote: true, html: { class: 'form-inline' }) do |f| %>
Note the remote: true part that is added as an argument to the form_for helper.
You need to include remote: true in form_for in order to make the call requests AJAX instead of HTML.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), remote: true, method: :post, html: { class: 'form-inline' }) do |f| %>
Check out the Working with JavaScript in Rails documentation for more information.

Rails post delete functionality giving template error

I am trying to have a link to delete a certain reservation from the database. This is my solution but it keeps giving Template Error. It shouldn't render the view but it is.
def delete
#current = Reservations.find(params['reservations']['id'])
respond_to do |format|
if current_user
if #current.user_id == current_user.id
#current.destroy
format.html { redirect_to :back }
else
format.html { redirect_to root_path }
end
else
format.html { redirect_to root_path }
end
end
end
My routes file
post "reservations/delete", to: 'reservations#delete', as: 'delete_reservation'
My view that includes the delete link:
<%= form_for item, :url => {:controller => 'reservations', :action => 'delete'}, :method => 'post' do |f| %>
<%= f.hidden_field :id, :value => item.id %>
<%= f.submit "Delete", :class =>'btn btn-danger btn-small' %>
<% end %>

ArgumentError in SongsController#create missing required :bucket option

I've been trying to get paperclip working with amazon s3 all day and I'm gettin' pretty close.
Albeit, how do I get around this error? I've included the bucket in the song model so I'm not sure what it's asking for. Once this is solved it should work.
Error:
ArgumentError in SongsController#create
missing required :bucket option
respond_to do |format|
if #song.save
format.html { redirect_to #song, notice: 'Song was successfully created.' }
format.json { render action: 'show', status: :created, location: #song }
else
song.rb
class Song < ActiveRecord::Base
acts_as_voteable
belongs_to :user
has_many :comments, :dependent => :destroy
has_many :genre_songs
has_many :genres, through: :genre_songs
has_attached_file :track,
:storage => :s3,
:path => '/:class/:attachment/:id_partition/:style/:filename',
:url => ":s3_domain_url",
:bucket => ENV['bucketname']
validates_attachment :track, :presence => true
validates_presence_of :url
validates :title, length: { minimum: 10 }
validates :url, length: { maximum: 300 }
def self.tagged_with(name)
Genre.find_by_name!(name).songs
end
def tag_list
genres.map(&:name).join(", ")
end
def tag_list=(names)
self.genres = names.split(",").map do |n|
Genre.where(name: n.strip).first_or_create!
end
end
end
paperclip.rb
# config/initializers/paperclip.rb
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
production.rb and development.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['my bucketname'],
:access_key_id => ENV['my access key'],
:secret_access_key => ENV['my secret access key']
}
}
show.html.erb
<p id="notice"><%= notice %>
<p>
<%= #song.title %> | ( <%= #song.url %> )
<br />
<span class="subtext"><span class="votes_<%= #song.id %>"><%= pluralize(#song.votes.count, 'like') %>,</span>
posted <%= time_ago_in_words(#song.created_at) + " ago" %>
<small><span class="comments"></small> | <%= pluralize(#song.comments.size, 'comment') %></span></small><br /></span></span>
</p>
<p>
<%= audio_tag (#song.track.url), controls: "controls", alt: "Please use chrome, ie, or safari", preload: :auto %>
</p>
<p>Genres: <%= raw #song.genres.map(&:name).map { |t| link_to t, genre_path(t) }.join(', ') %></p>
<%#= link_to 'Show', song, class: "button small secondary" %>
<%= link_to('Edit', edit_song_path(#song), class: "button small secondary") if can? :update, #song %>
<%#= link_to 'Back', songs_path, class: "button small secondary" %>
<br /><br />
<%= render :partial => 'comments/form' %>
<div class="replies">
<% unless #song.comments.empty? %>
<h5><%= pluralize(#song.comments.size, 'comment') %></h5>
<br />
<% end %>
<% if #song.comments.empty? %>
<p>There are no comments...</p>
<% else %>
<div id="comments">
<% for comment in #song.comments %>
<div class="comment">
<strong><%= link_to_unless comment.site_url.blank?, h(comment.author_name), h(comment.site_url) %></strong>
<em>on <%= comment.created_at.strftime('%b %d, %Y at %H:%M') %></em>
<%=simple_format comment.content %><hr>
<p>
<%= link_to("Edit", edit_comment_path(comment)) if can? :update, #comment %>
<% end %>
<%= link_to("Destroy", comment, :method => :delete, :confirm => "Are you sure?") if can? :destroy, #comment %>
</p>
</div></div>
<% end %>
</div></div>
song_controller.rb
class SongsController < ApplicationController
before_filter :authenticate_user!, only: [:create ,:edit, :update, :destroy, :vote_for_song]
before_action :set_song, only: [:show, :edit, :update, :destroy, :vote_for_song]
def vote_for
#song = Song.find(params[:id])
current_user.vote_for(#song)
#song.plusminus = #song.votes_for
#song.save
respond_to do |format|
format.js { render 'update_votes' }
end
end
def vote_against
#song = Song.find(params[:id])
current_user.vote_against(#song)
respond_to do |format|
format.js { render 'update_votes' }
end
end
def new_songs
#songs = Song.order "id DESC"
end
# GET /Songs
# GET /Songs.json
def index
if params[:genre]
#songs = Song.tagged_with(params[:genre]).paginate(:page => params[:page], :per_page => 15)
else
#songs = Song.order('plusminus').paginate(:page => params[:page], :per_page => 15)
end
end
# GET /Songs/1
# GET /Songs/1.json
def show
#comment = Comment.new(song: #song)
end
# GET /Songs/new
def new
#song = Song.new
end
# GET /Songs/1/edit
def edit
end
# POST /Songs
# POST /Songs.json
def create
#song = Song.new(song_params)
respond_to do |format|
if #song.save
format.html { redirect_to #song, notice: 'Song was successfully created.' }
format.json { render action: 'show', status: :created, location: #song }
else
format.html { render action: 'new' }
format.json { render json: #song.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Songs/1
# PATCH/PUT /Songs/1.json
def update
respond_to do |format|
if #song.update(song_params)
format.html { redirect_to #song, notice: 'Song was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #song.errors, status: :unprocessable_entity }
end
end
end
# Song /Songs/1
# Song /Songs/1.json
def destroy
#song.destroy
respond_to do |format|
format.html { redirect_to songs_url }
format.json { head :no_content }
end
end
private
def set_song
#song = Song.find(params[:id])
end
def song_params
params.require(:song).permit(:title, :artist, :url, :track, :user_id, :tag_list)
end
end
In dev and prod env you call:
ENV['my bucketname']
In model:
ENV['bucketname']
Also a good name for env variable would be:
ENV['MY_BUCKETNAME']
In your case:
ENV['AWS_BUCKET']
config.paperclip_defaults = {
:storage => :s3,
:bucket => ENV['BUCKETNAME'],
:s3_credentials => { :access_key_id => ENV['my access key'], :secret_access_key => ENV['my secret access key'] } }

rails: "unknown action" message when action is clearly specified

I had hard time to figure out why I've been getting "unknown action" error message when I was do some editing:
Unknown action
No action responded to 11. Actions: bin, create, destroy, edit, index, new, observe_new, show, tag, update, and vote
you can see that Rails did mention each action in the above list - update. And in my form, I did specify action = "update".
I wonder if some friends could kindly help me with the missing links...
here is the code:
edit.rhtml
<h1>Editing tip</h1>
<% form_tag :action => 'update', :id => #tip do %>
<%= render :partial => 'form' %>
<p>
<%= submit_tag_or_cancel 'Save Changes' %>
</p>
<% end %>
_form.rhtml
<%= error_messages_for :tip %>
<p><label>Title<br/>
<%= text_field :tip, :title %></label></p>
<p><label>Categories<br/>
<%= select_tag('categories[]', options_for_select(Category.find(:all).collect {|c| [c.name, c.id] }, #tip.category_ids), :multiple => true ) %></label></p>
<p><label>Abstract:<br/>
<%= text_field_with_auto_complete :tip, :abstract %></label></p>
<p><label>Name: <br/>
<%= text_field :tip, :name %></label></p>
<p><label>Link: <br/>
<%= text_field :tip, :link %></label></p>
<p><label>Content<br/>
<%= text_area :tip, :content, :rows => 5 %></label></p>
<p><label>Tags <span>(space separated)</span><br/>
<%= text_field_tag 'tags', #tip.tag_list, :size => 40 %></label></p>
class TipsController < ApplicationController
before_filter :authenticate, :except => %w(index show)
# GET /tips
# GET /tips.xml
def index
#tips = Tip.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #tips }
end
end
# GET /tips/1
# GET /tips/1.xml
def show
#tip = Tip.find_by_permalink(params[:permalink])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #tip }
end
end
# GET /tips/new
# GET /tips/new.xml
def new
#tip = session[:tip_draft] || current_user.tips.build
end
def create
#tip = current_user.tips.build(params[:tip])
#tipMail=params[:email]
#if tipMail
# TipMailer.deliver_email_friend(params[:email], params[:name], tip)
# flash[:notice] = 'Your friend has been notified about this tip'
#end
#tip = current_user.tips.build(params[:tip])
#tip.categories << Category.find(params[:categories]) unless params[:categories].blank?
#tip.tag_with(params[:tags]) if params[:tags]
if #tip.save
flash[:notice] = 'Tip was successfully created.'
session[:tip_draft] = nil
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#tip = Tip.find(params[:id])
end
def update
#tip = Tip.find(params[:id])
respond_to do |format|
if #tip.update_attributes(params[:tip])
flash[:notice] = 'Tip was successfully updated.'
format.html { redirect_to(#tip) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #tip.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#tip = Tip.find(params[:id])
#tip.destroy
respond_to do |format|
format.html { redirect_to(tips_url) }
format.xml { head :ok }
end
end
def observe_new
session[:tip_draft] = current_user.tips.build(params[:tip])
render :nothing => true
end
end
the quick answer is that form_tag doesn't support :action as an option, you want to be passing a string as a path in. A slightly longer answer is you shouldn't be using form_tag anyways for a model edit form, you should be using form_for.
what rails are you using? .rhtml is pretty old, rails generators should be giving you .html.erb files. if it is something even remotely recent, you should be able to use
<% form_for #tip do |f| %>
<%= f.label :title, 'Title' %><br />
<%= f.text_field %>
... etc
<% end %>

Resources