Change button_to attribute - ruby-on-rails

Im new to ruby on rails and im currently working on a button that will change the attribute depends on the functions result. as of now i create this function that returns true or false.
def link_facebook
is_linked = FacebookLinked.link(env["omniauth.auth"])
redirect_to :controller => 'dashboard', :action => 'settings'
end
i want to change my button_to attribute(Value,class, and make it disable)
if the result retuns true.
<%= button_to 'Setup Facebook','/auth/facebook',:class=>'btn btn-default',:id=>'setup_facebook'%>
i've search ajax but i have no clue on how to start using it.

Method 1
You can do something like this
redirect_to controller: 'dashboard', action: 'settings', is_linked: is_linked
Now is linked value will passed to the settings page's url
http://localhost:3000/dashboard/settings?is_linked=true
In your view
<%= button_to 'Setup Facebook','/auth/facebook',:class=>"btn btn-default #{params[:is_linked]? '': 'disabled'}",:id=>'setup_facebook'%>
Method 2
You can have an instance variable inside your settings action in rails, Like this
def settings
#is_linked = FacebookLinked.link(env["omniauth.auth"])
...
end
So you can access in your view in a similar fashion
<%= button_to 'Setup Facebook','/auth/facebook',:class=>"btn btn-default #{#is_linked? '': 'disabled'}",:id=>'setup_facebook'%>

If the function that returns a boolean is called my_function, the default class (when true) is 'btn btn-default' and the class when the boolean is false is 'btn btn-default disabled' then you could use :
"btn btn-default #{(my_function ? '': 'disabled')}"
So overall :
<%= button_to 'Setup Facebook','/auth/facebook',:class=>"btn btn-default #{(my_function ? '': 'disabled')}",:id=>'setup_facebook'%>
Please note that you might need to use a helper to call the method from the view, as follows : helper_method :my function. Alternatively, you could create the variable in the controller (no need for helper) and pass the variable to the view.

Related

Rails navigation helper method

I have two rails helper on my application helper:
def active_class(link_path)
current_page?(link_path) ? 'active' : ''
end
def active_class_white(link_path)
current_page?(link_path) ? 'active-white' : ''
end
One is for regular links the other one is for the submenus. Usually I place the link like this:
<%= link_to "Home", root_path(:anchor => 'home'), class: "nav-link #{active_class('/')}", :"data-id" => "home" %>
Now here's my problem. On my homepage I got this link where it will slide to a particular section of the site thus requires a character like #about. If I place:
<%= link_to "About", root_path(:anchor => 'about'), class: "nav-link #{active_class('/#about')}", :"data-id" => "about" %>
It's still putting the active class on the home text instead of the about (the homepage is a one page slider type).
Another thing is that for complicated url like the devise edit profile, I tried to put the ff:
<%= link_to "Edit Profile", edit_user_registration_path(current_user), class: "dropdown-item #{active_class_white('/users/edit/:id')}" %>
Placing /users/edit/:id doesn't work on this kind of URL: http://localhost:3000/users/edit.13
On this two kinds of URL my code doesn't work. Any idea how to make them work or turn this around?
Anchors are purely client-side and are not sent along with the request to the server. So, the only way to implement the first part of your question is through Javascript. You can listen for a click event on links then add the active class to the one that was clicked.
The second part of your question, where you pass in the :id segment key, can be solved by passing a route helper (along with an object) to current_page? instead of an explicit string...
class: <%= active_class(edit_user_registration_path(current_user)) %>

Rails 4 - current_page? with query parameter

I've method in my application.rb
def current_page(path)
"active" if current_page?(path)
end
then in my view, lets say the request_uri is http://www.example.com/stories, i just can call
<%= link_to "All Stories", stories_path, :class => "#{current_page(stories_path)}" %>
BUT how about if the request_uri has something like http://www.example.com/stories?featured=true ? How do I call it in view?
Because current_page? method will compare passed-in path which doesn't have ? just with your current url deleting query params.
For example, if you're at http://www.example.com/stories?featured=true, and you have current_page(stories_path), you'll still compare http://www.example.com/stories(stories_path) with http://www.example.com/stories(your current url without featured=true).
I have a idea, but you'll have ? in the end of your normal url.You can change the code to <%= link_to "All Stories", stories_path + '?', :class => "#{current_page(stories_path + "?")}" %>
I'll update this if I come up with better methods.

Calling a (helper) method from a view with two arguments

I'm having problems with calling a (helper) method in a controller from a view.
I had a helper method which i simply called in a link_to but i had problems with that and i went to look for answers to this problem and i discovered that you cannot simply call a helper method from a view that way, so i tried to follow the recommendations of another answer but it's still not working.
I'm getting this error:
No route matches [GET] "/pages/associateplace.5"
In the view (pages/associate_place_to_activity.html.erb) i have this:
<%= link_to "Choose Place", pages_associateplace_path(#activity.id, place.id), :class => 'btn btn-default btn-xs' %>
In the controller (pages_controller) i have this:
def associateplace
#activity_id = params[:activity_id]
#place_id = params[:place_id]
Activity.find(activityid).place_id=placeid
redirect_to Activity.find(activityid)
end
ยด
And in the routes.rb i have this:
put 'pages/associateplace/:activity_id/:place_id' => 'pages#associateplace', as: :associateplace
You didn't call it pages_associateplace. You called associateplace. So in your link_to you should take off the pages_ part and leave only: associateplace_path(#activity.id, place.id)
There is one more thing. You've created a PUT route. But in a link_to you need to specify that it is a PUT that you want since GET is the default. So you need to write:
<%= link_to "Choose Place", associateplace_path(#activity.id, place.id), method: :put %>

how to use click event in rails 4

My code:
<%#categories.each_with_index do |d,index| %>
<%= link_to d.name ,{:action=>'index',:id=>d.id,:hotel_id=>d.hotel_id},class: "btn-orange" %>
<%end%>
In my Controller:
def index
#category = Category.where(:hotel_id => params[:hotel_id]).first
#menus2=Menu.where(:category_id=> #category.id).sorted
#categories=Category.where(:hotel_id=>params[:hotel_id])
#cart = current_cart
if params[:name]==params[:name]
#menus=Menu.where(:category_id=> params[:id]).sorted
else
end
end
I am new in rails.I want to use #menus2=Menu.where(:category_id=> 0).sorted this code when link_to is clicked.How can i do in my controller, is there any click event in ROR.
You can add a remote attribute to your link_to method:
= link_to d.name, controller_index_path, class: 'btn etc', remote: true
This will allow Rails to make an 'Ajax' call to your desired controller.
Note: when making a remote call such as this, Rails will receive/respond via .js. This means that you need to have an index.js.erb file that does what you need and reports back to the 'Ajax' caller whatever data is necessary.
This page in the Rails guide may help with additional details, etc.: Working with JavaScript in Rails

Rails: Multi-submit buttons in one Form

Say I have an Article model, and in the article 'new' view I have two buttons, "Publish" and "Save Draft".
My question is how can I know which button is clicked in the controller.
I already have a solution but I think there must be a better way.
What I currently used in the view is:
<div class="actions">
<%= f.submit "Publish" %>
<%= f.submit "Save Draft", :name => "commit" %>
</div>
So in the controller, I can use the params[:commit] string to handle that action.
def create
#article = Article.new(params[:article])
if params[:commit] == "Publish"
#article.status = 'publish'
// detail omitted
end
#article.save
end
But I think using the view related string is not good. Could you tell me another way to accomplish this?
UPDATE: Since these buttons are in the same form, they're all going to the 'create' action, and that's OK for me. What I want is to handle that within the create action, such as give the Article model a 'status' column and holds 'public' or 'draft'.
This was covered in Railscast episode 38. Using the params hash to detect which button was clicked is the correct approach:
View:
<%= submit_tag 'Create' %>
<%= submit_tag 'Create and Add Another', name: 'create_and_add' %>
Controller:
if params[:create_and_add]
# Redirect to new form, for example.
else
# Redirect to show the newly created record, for example.
end
it can also be done on the form_for helper like this
<%= f.submit "Publish",name: "publish", class: "tiny button radius success" %>
<%= f.submit 'Mark as Draft', name: "draft", class: "tiny button radius " %>
and the logic is the same on the controller
if params[:publish]
// your code
elsif params[:draft]
// your code
end
We solved using advanced constraints in rails.
The idea is to have the same path (and hence the same named route & action) but with constraints routing to different actions.
resources :plan do
post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end
CommitParamRouting is a simple class that has a method matches? which returns true if the commit param matches the given instance attr. value.
This available as a gem commit_param_matching.
I remember coming across this problem once. You cannot keep two buttons and then call some action based on the params[:commit]. the submit button onclick is going to call the url the form refers to. There are certain bad ways to get the desired behavior. Keep a button to call the action the form refers to and to get another button to call a action, I used a link_to and then changed the styles to match a button. Also, alternatively you can use jQuery to change the url the form would call, hence deciding what action is invoked at run-time. Hope this helps.
You could also set some data attributes on the submit buttons and use JavaScript to change out the form action on click of one of the buttons
usually i using the suggestion given by John Topley (see answer above).
another way is using JQuery /JS changing the form action attribute- upon clicking the submit button
example:
form_tag({} ,:method => 'post', :id => 'reports_action') do
.......
.......
submit_tag 'submit', :onclick => "return changeAction();"
end
and then .....
function changeAction(){
$('#reports_action').attr('action','my_new_action');
}

Resources