Rails button to disable if data is in database - ruby-on-rails

I have a button that i need disabling if the data it was going to submit already exists in the database.
Bare in mind ive only been using this for like a month. so im a super noob!! haha!
The button is this <%= link_to 'Table', admin_table_statuses_path(table_id: #table.id), class: "btn btn-primary", method: :post, remote: true%>
my controller for this button is pretty basic also. see here
def create
table_id = params[:table_id] #Keep the same
#table_status = tableStatus.new
#table_status.table_id = params[:table_id]
#table_status.invoiced_out_user_id = current_user.id
#table_status.invoiced_out_datetime = DateTime.now
if #table_status.save
# Success
flash[:notice] = "Done!"
else
flash[:notice] = "Fail"
end

Give an ID to the button:
<%= link_to 'Table', admin_table_statuses_path(table_id: #table.id), class: "btn btn-primary", id: 'create_button',method: :post, remote: true%>
Inside create method do:
def create
.
.
.
render :update do |page|
if #table_status.save
page << "document.getElementById('create_button').setAttribute('href', '')"
end
end
end
Since, the element is a link not button, you can just remove it's href, so that it doesn't hit create method again.

Related

Rails routes confuses a custom destroy method with destroy method in users controller

I have a users controller with the following two destroy methods:-
def destroy
#user = User.find_by(params[:id])
#user.destroy
flash[:success] = "Account successfully closed"
redirect_to root_path
end
def destroy_avatar
#user = User.find_by(params[:id])
#user.remove_avatar!
#user.save
render 'edit'
end
The first is the default destroy method that deletes the user. The second is one that I defined to let the user delete their avatar from their user edit page.
I had the following defined in the routes.rb to get the destroy_avatar working:-
delete '/users/:id', to: 'users#destroy_avatar', as: 'destroy_avatar'
resources :users
But unfortunately when I implemented this the close account button I had on the user edit page reverted to the destroy_avatar action.
This is the call to both the actions from the view:-
.
.
.
<% if current_user.avatar_url %>
<%= link_to "Delete avatar", destroy_avatar_path,
method: :delete,
data: {:confirm => 'Are you sure?'},
class: 'btn btn-xs btn-danger',
"data-toggle" => "tooltip",
"data-placement" => "right",
"title" => "Delete avatar" %>
.
.
.
<%= link_to "Close account", user_path(#user),
method: :delete,
data: {:confirm => "Are you sure?"},
class: "btn btn-xs btn-danger"%>
.
.
.
I went looking to see if there is a way to get the destroy_avatar to work without using routes, but I found a way to do it with AJAX without requiring an additional route, which would actually be more convenient but I don't know Javascript and couldn't customize the code to my case.
I am still learning rails and I don't know what I don't know! So I would like to know what options I have.
Is there a way to do this without using two routes? If no, how should I customize the route for the destroy_avatar so that there is no conflict with the route for user destroy action?
Ok, I figured it out.
Changed the route to
delete '/users/:id/destroy_avatar', to: 'users#destroy_avatar', as: 'destroy_avatar'
and from the view:
<%= link_to "Delete avatar", "/users/#{#user.id}/destroy_avatar" %>

How to save follower data?

I have a table user_followers that has: user_id and follower_id
I'm trying to save a new record where the logged in user follows another user via AJAX.
this is the button:
<%= link_to "Add friend", teste_user_follower_path(:params => #friend.id), remote: true, class: 'btn' %>
And the action teste where I try to save:
def teste
if params[:query]
#friend = User.where(id: params[:query]).first
#user_follower = current_user.user_followers.new(follower: #friend)
else
flash[:error] = "Friend required"
end
end
I have the associantions set up correctly I think
If you're creating a record I assume that you've set up your teste route as POST. If this is the case you'll have to add method: :post to your link_to
<%= link_to "Add friend", teste_user_follower_path(:params => #friend.id), method: :post, remote: true, class: 'btn' %>
It also doesn't look like you're actually saving the record anywhere. You're calling new but never calling save. If you want to do both at once you can use create
def teste
if params[:query]
#friend = User.where(id: params[:query]).first
#user_follower = current_user.user_followers.create(follower: #friend)
else
flash[:error] = "Friend required"
end
end
You are not actually creating anything in your code.
Here is the documentation about associations: http://guides.rubyonrails.org/association_basics.html#detailed-association-reference
You should do something like:
#user_follower = current_user.user_followers.create(follower: #friend)

Why does variable pass on create, but not on destroy?

I have a form on the chords/:id/show page (shown below). I am able to input a :note_id into the form, which then creates a ChordNote using the :chord_id from :params and the :note_id from the form. This works well. However, when I try to delete a ChordNote using the same form, I get an error that says:
NoMethodError in ChordNotesController#destroy, undefined method '[]' for nil:nilClass
This is the controller for 'ChordNote', which joins chords and notes in a many-to-many relationship.
def create
#chord = Chord.find(params[:chordnote][:chord_id])
#note = Note.find(params[:chordnote][:note_id])
if #chord.hasnote?(#note)
# Add error message here, have it not redirect
redirect_to #chord
else
#chord.addnote!(#note)
redirect_to #chord
end
end
def destroy
#chord = Chord.find(params[:chordnote][:chord_id])
#note = Note.find(params[:chordnote][:note_id])
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
end
This is the form (that appears on chords/:id/show):
<%= form_for(#chord.chordnotes.build(chord_id: #chord.id)) do |f| %>
<div><%= f.hidden_field :chord_id, value: #chord.id %></div>
<div class="field">
<%= f.text_field :note_id, placeholder: "Enter the note's id" %>
</div>
<%= f.submit "Add Note", class: "btn btn-large" %>
<%= link_to "Remove Note", Chordnote.find_by(note_id: 1), method: :delete, title: "test title", class: "btn btn-large" %>
<% end %>
Any thoughts on why destroy is not working? Thanks!
undefined method `[]' for nil:NilClass
def destroy
####The error is on the following line####
#chord = Chord.find(params[:chordnote][:chord_id])
#note = Note.find(params[:chordnote][:note_id])
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
Rails.root: /Users/mydocs/myprojects/rails_projects/what_key_v002
Application Trace | Framework Trace | Full Trace
app/controllers/chordnotes_controller.rb:23:in `destroy'
Request
Posted parameters:
{"_method"=>"delete",
"id"=>"10"}
In your destroy action, you're trying to make a lookup off params[:chordnote][:note_id], but the only available parameters are {"_method"=>"delete", "id"=>"10"}. You need to add both note_id and chord_id as arguments in your link_to helper:
<%= link_to "Remove Note", chordnote_path(:chord_id => #chord.id, :note_id => 1), :method => :delete %>
# => Remove Note
Then, in your destroy action, make your lookups off params[:chord_id] and params[:note_id]:
def destroy
Chordnote.find_by(note_id: params[:note_id], chord_id: params[:chord_id]).destroy
redirect_to chord_path(params[:chord_id])
end
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id)
cant find a record, so its nil and nil doesnt have a method called destroy.
Are you sure you are passing the correct params to the action?
Update:
params[:chordnote] #seems to be nil, so
params[:chordnote][:note_id] => exception
Check the params which are posted to the action. You can see it in your console logs.
Update:
Your link should maybe be something like this:
<%= link_to "Remove Note", chord_notes_path(note_id: 1, chord_id: #chord.id), method: :delete, title: "test title", class: "btn btn-large" %>
And in your delete action
#chord = Chord.find(params[:chord_id])
#note = Note.find(params[:note_id])

Rails Button to Update Attribute Not Working

I have a link that looks like this in the object's show view:
<%= link_to "Approve", object_path(#object, status: true), method: :put, confirm: "Are you sure?", class: 'button' %>
The update action in the controller is standard and the object's regular edit form works just fine. But for some reason, this link isn't updating the boolean field to true...
Is there something that I did wrong with this link?
EDIT: Update Section of Controller
def update
#object = Object.find_by_certain_field(params[:id])
if #object.update_attributes(params[:object])
flash[:success] = "Object Updated"
redirect_to #object
else
render 'edit'
end
end
object_path(#object, status: true) causes params[:status] to be true and not params[:object][:status] as you wish, thus not updating the object with #object.update_attributes(params[:object])
If you want to keep using the current code pattern just add
parmas[:object] ||= {}
params[:object][:status] = params[:status] if params[:status]
before
if #object.update_attributes(params[:object])
and everything should be fine.
Otherwise I'd avise you to make a form for this update call:
<% form_for #object, :method => :put do |f| %>
<%= f.hidden_field :status, :value => true %>
<%= f.submit "Approve" %>
<% end %>

Rails 3 - Forms, Custom Submit Button based on Action?

I currently have a couple of forms that I'm trying to change the button that submits it based if I'm on the edit or new action. I had two forms created but this smelt bad, and am now just using a single form partial.
At the end of my partial, I have something like this at the end of my forms:
<p>
<% if controller.action_name == 'new' %>
<%= f.submit "Create", :class => "pink_button"%> or
<% elsif controller.action_name == 'edit' %>
<%= f.submit "Update", :class => "pink_button"%> or
<% end %>
<%= link_to "cancel", :back %>
</p>
That way, if I'm creating some new, the button reads "Create", and if it's an update that a user is trying to complete, the button reads "Update". This works great, until the form is submitted and validation fails.
In my controller, I'm catching things that do fail like so:
def update
#list = current_user.lists.find(params[:id])
if #list.update_attributes(params[:list])
redirect_to list_path(#list), :notice => "List '#{#list.name}' updated."
else
render :action => 'edit'
end
end
So the form is simply re-rendered. The problem is, I'm no longer on the edit path. This means, my form button does not show up any longer.
Is there a convention to what I'm trying to do?
Thanks
Yes, this is handled in Rails with i18n by default. The translations are in ActionView, and look like this:
en:
helpers:
select:
# Default value for :prompt => true in FormOptionsHelper
prompt: "Please select"
# Default translation keys for submit FormHelper
submit:
create: 'Create %{model}'
update: 'Update %{model}'
submit: 'Save %{model}'
All you need to do is f.submit (without passing "Create" or "Edit", etc) and the translations will do the rest. You can overwrite these by dropping the above yaml into your local locales.
If you need to set the class you can pass nil, e.g. f.submit nil, :class => 'whatev'
The Rails way is to check if the record is new or not:
#list.new_record? ? "Create" : "Update"
Rails has a method persisted? to determine if an object has persisted.
If you're using erb, do
<%= f.submit (#list.persisted? ? 'Create' : 'Update) %>
If you're using haml, use
= f.submit (#list.persisted? ? 'Create' : 'Update')
For more, see http://apidock.com/rails/ActiveRecord/Persistence/persisted%3F

Resources