rails conditional form/remote_form - ruby-on-rails

I have a form partial that needs to render a remote_form_for or a form_for depending on the value of a local variable passed into it from the caller view. It looks like...
<% if ajax %>
<% remote_form_for #search, :url => {:action => :search_set, :controller => :searches, :stype => stype} do |f| %>
<% else %>
<% form_for #search, :url => {:action => :search_set, :controller => :searches, :stype => stype} do |f| %>
<% end %>
Obviously, I am getting a syntax error near the <%else %>, because its expect an "end".
What's the right way to do this?

you could make a helper method
def form_or_remote_form_for object, *opts, &proc
if ajax
remote_form_for object, *opts, &proc
else
form_for object, *opts, &proc
end
end
and then in your views it'd just be
<% form_or_remote_form_for #search, :url => {:action => :search_set, :controller => :searches, :stype => stype} do |f| %>

Related

Trying to do simple_form_for on the following example code

I'm new to ruby-on-rails and trying to refactor the following form_tag into simple_form_for code and I was getting a weird error in log stating:
"customers_customers_customers_path' no methods found.
Any idea on which part of the code is wrong?
<%= form_tag projects_path, :method => 'get', :id => "ajax_search_form" do %>
...
<% end %>
I refactor it into:
<%= simple_form_for #projects, :html => { :id => 'ajax_search_form' }, :method => 'get' do |f| %>
...
<% end %>
What am I doing wrong?
simple_form_for is mainly used to associate the form to a model just like form_for does. In your code, you used form_tag to associate to a path, not a model. The right way to implement simple_form_for here is:
<%= simple_form_for :projects, :url => projects_path, :method => 'get', :id => "ajax_search_form" do $>
...
<% end %>

Rails3 display form_for form gives routing error if on other erb page

I have a'Remove' button in a show erb of the trackers_controller.show:
<%= form_for :user_tracker, :url => user_tracker_path,:method => :delete do |f| %>
<%= f.hidden_field :tracker_id, :value => #tracker.id %>
<%= f.submit :save, :value => 'Remove' %>
<% end %>
This works fine and calls user_trackers_controller.destroy
The User models looks like:
has_many :user_trackers
has_many :trackers, :through => :user_trackers
If I put the exact same button in another erb I get this error:
No route matches {:action=>"show", :controller=>"user_trackers"}
I have a few different combinations like :html => {:method => :delete }
If I try it this way
<% current_user.user_trackers.each do |user_tracker| %>
<%= user_tracker.tracker %>
<%= form_for user_tracker, :method => :delete do |f| %>
<%= f.submit :delete, :value => 'Remove' %>
<% end %>
I get the same routing error
Here are the routes:
user_trackers GET /user_trackers(.:format) user_trackers#index
POST /user_trackers(.:format) user_trackers#create
new_user_tracker GET /user_trackers/new(.:format) user_trackers#new
edit_user_tracker GET /user_trackers/:id/edit(.:format) user_trackers#edit
user_tracker GET /user_trackers/:id(.:format) user_trackers#show
PUT /user_trackers/:id(.:format) user_trackers#update
DELETE /user_trackers/:id(.:format) user_trackers#destroy
I do not understand, why will it not pick up that this is a destroy when in an unrelated erb?
Edit:
This is one seems to work but the html generates ids and classes like edit_user_tracker_7 but also the javascript to make it a delete so it seems I still have something wrong:
<%= form_for user_tracker, :url => user_tracker_path(user_tracker), :method => :delete do |f| %>
<%= f.hidden_field :tracker_id, :value => user_tracker.tracker_id %>
<%= f.submit :delete, :value => 'Remove from my portfolio' %>
<% end %>
in first line it should be
:url => user_tracker_path(#user)
Its not a bug, he just have to know who to remove :) so he needs id (in REST).
Also :method should be in :html
:html => { :method => :delete }
or
html: { method: "delete" }
with 1.9+ notation.
full form_for
user_tracker_path(#user), :html => {:method => :delete} do |f| %>
ofc if in your case #user is current_user then you have to swap it :)
Sorry for typos & english i'm not native :)
Cheers!

Cant pass local object to nested partial in Rails 3

Im hoping that someone can shed light on what is probably a simple mistake. Im trying to pass a local variable, article, which is in the partial _article.html.erb, to another partial nested within _article.html.erb. When the partial code is in _article.html.erb, it works fine.I've tried many variations (including :locals) but cant seem to pass the local variable.
_article.html.erb
<% if current_user.favorited?(article) %>
<%= render :partial => 'unfavorite', :object => article %>
<% else %>
<%= render :partial => 'favorite', :object => article %>
<% end %>
_favorite.html.erb (both favorite and unfavorite are more or less the same, so I've only posted one)
<%= form_for current_user.favorites.find_by_article_id(article), :html => { :method => :delete, :class => 'unfavorite_form', }, :remote => true do |f| %>
<div><%= f.hidden_field :article_id %></div>
<%= image_submit_tag("vote-favorite-on.png", :alt => "Favorite", :id => "favorites_button", :title => "Remove from favorites") %>
<% end %>
The error message is:
undefined local variable or method `article' for #<#<Class:0x491c2b0>:0x6727a58>
The rails docs for rendering mention the use of object like this:
<%= render :partial => "customer", :object => #new_customer %>
And say that:
Within the customer partial, the customer variable will refer to #new_customer from the parent view.
Which makes it seem like the :object variable is translated into the name of the partial. So in your case, in _favorite, you'd have to use the favorite variable:
<%= form_for current_user.favorites.find_by_article_id(favorite), :html => { :method => :delete, :class => 'unfavorite_form', }, :remote => true do |f| %>
Personally I prefer the locals syntax, because then you can be explicit:
<%= render :partial => 'favorite', :locals => {:article => article} %>

In Rails 3, is form_for supposed automatically know when a model's named helpers are overridden?

In my routes file I have:
resources :features, :as => 'featured'
However, when I use the following:
<% form_for #feature, :html => { :multipart => true } do |f| -%>
<%= render :partial => "form", :locals => { :f => f } -%>
<p><%= submit_tag "Feature these submissions" -%></p>
<% end -%>
I receive this error:
"undefined method `features_path' for #<#:0x00000106228ec0>"
This is my "new" method in the "features_controller":
def new
#feature = Feature.new
#submissions = Submission.find(pending_featured_submissions)
end
Before I upgraded to Rails 3, Rails was able to figure out that I was using a custom named helper. Now it seems as though form_for is ignoring the line in my resources file and using features_path, when it should be used featured_path.
Maybe I'm doing something wrong, or missing something.
Thanks for looking =)
For what its worth I ended up having to specify the url in the form builder.
<% form_for #feature, :url => featured_index_path, :html => { :multipart => true } do |f| %>
You are using submit_tag. If you used the form object to submit then your path will be as defined in the form_for so instead of
<% form_for #feature, :html => { :multipart => true } do |f| -%>
<%= render :partial => "form", :locals => { :f => f } -%>
<p><%= submit_tag "Feature these submissions" -%></p>
<% end -%>
you should use
<%= form_for #feature, :html => { :multipart => true } do |f| -%> //Note the = sign
<%= render :partial => "form", :locals => { :f => f } -%>
<p><%= f.submit "Feature these submissions" -%></p>
<% end -%>
Note that because you are in Rails 3 not Rails 2, you should use the = symbol in your form declaration

Rails tries to execute Update action instead of the one I want

I want to develop an ajax functionality for commenting posts in my website.
I've done this before, but I don't know why I'm having problems this time. Rails executes Update action from posts_controller, instead of the action called "save_comment".
This is the relevant line of my routes file:
map.connect "/posts/save_comment", :controller => 'posts', :action => 'save_comment'
This is the view's code:
<%= javascript_include_tag "prototype" %>
<% if logged_in? %>
<% remote_form_for :post, PostComment.new, :url => {:action => 'save_comment',:post_id=>inside_list.id}, :html => { :method => :put} do |f| %>
<p>
<%= f.label 'Comment' %><br />
<%= f.text_area :comment, :style=>'height:100px;' %>
</p>
<p>
<%= f.submit 'Publish' %>
</p>
<% end %>
<% end %>
The save_comment action looks like this:
def save_comment
comment = PostComment.new
comment.user_id = current_user.id
comment.post_id = params[:post_id]
comment.comment = params[:post][:comment]
comment.save
post = Post.find(params[:post_id])
render :update do |page|
page.replace_html 'dComments', :partial => 'post_comments/inside_list', :object => post
end
end
BTW: Is there a neater way for doing this?
You need to define the route method. Also you're not defining the post parameter.
map.connect "/posts/:post_id/save_comment", :controller => 'posts', :action => 'save_comment', :method => :post
Following convention you should make the route method => :post, rather than :put. Put requests are generally used for updating existing records, post for creating new. Also how about named routes?
#routes.rb
map.save_comment "/posts/:post_id/save_comment", :controller => 'posts', :action => 'save_comment', :method => :post
#view
<% remote_form_for :post, PostComment.new, :url => save_comment_path(inside_list.id) do |f| %>
Also, guessing here but do you have this defined:
map.resources :posts
if you do then add the new method
map.resources :posts, :member => {:save_comment => :post}

Resources