Syntax to route Rails form_for to custom controller - ruby-on-rails

Have tried forums, documentation and blog suggestions. They converge on syntax that for me does not properly save AND route through desired controller.
Big picture, I have two software applications that share functionality. To implement shared functionality, I had Rails generate Shared::Widgets. This MVC works just fine. No problem viewing, updating, creating, or deleting using standard shared/widgets & etc routing.
Then, for the product-specific functionality, I created two controllers: Product1::Widgets and Product2::Widgets. Both inherit from Shared::Widgets controller. Both are empty except for product-specific layouts.
This scheme almost works. When I route to product1/widgets, it sets layout to product1 and invokes index method of shared/widgets. The result is display of shared/widgets/index.html.erb with product1 layout. Similarly, when I route to product2/widgets, this sets product2 layout and invokes index method of shared/widgets. The result is display of shared/widgets/index.html.erb with product2 layout. Perfect.
But now we get to the form_for. Because it implements the rails magic, it really really wants to route directly to Shared::Widgets controller. But that's not what I want. I want it to route to the appropriate product controller so as to set layout. The rails generated form_for was something like this:
form_for(#shared_widget, :html => { :class => "form"}) do |f|
I tried:
form_for([:product1, #widget], :html => { :class => "form"}) do |f|
but that duplicates namespace (product1_widget_shared_widget_path).
I tried the following three formats, all of which seem to route correctly, and save the record, but the record is empty (columns are blank):
form_for(#widget, url => "product1/widget", :html => { :class => "form"}) do |f|
form_for(#widget, url => url_for(:controller => "widget"), :html => { :class => "form"}) do |f|
form_for(#widget, url => url_for(:controller => "widget", :action => "create"), :html => { :class => "form"}) do |f|
Any help? If the above code has spelling errors, it is due to transcription. The actual code I used passed the interpreter. Thank you.

try this
form_for(url: { controller: "posts", action: "create" }, html => { :class => "form" }, method: "post") do |f|

Related

Rails passing a list of objects to another controller with link_to_remote

Is it possible to pass a list of objects to another controller in Ruby on Rails?
I have experimented with the following example:
class Student
...
end
student_list = [std1, std2, ... stdn]
When I use
<%= link_to_remote("example", :url => {:controller => 'class/assignment',
:action => 'homework',
:student => student_list})%>
It did not work the way I expected. params[:student] is equal to "student" (string literal).
Is there anything I did wrong, or an alternate way of doing it?

Rails: Setting class and data-tag of an HTML attribute with a single rails method

I'm currently working on a tour interface that guides new users around my site. I have a Tour model that has many TourStops, each of which contains information about a section of the site.
Basically, I'd like to write a function for the Tour model that -- when passed the number of a TourStop -- generates the correct class and data attribute for the HTML element it's attatched to. For example, I'd like
<%= link_to image_tag("new_button.png", tour.stop_data(1), :title => 'Add new asset'), new_asset_path %>
to call a function and return something like
def stop_data(order)
" :class => '#{tour_stops.find_by_order(order).name}',
:data => '{:order => order}'"
end
creating a link_to tag like:
<%= link_to image_tag("new_button.png", :class => 'tour_stop_1',
:data => {:order => 1}, :title => 'Add new asset'), new_asset_path %>
The above code doesn't work. Is something like this even possible? If not, what's a better approach I might take?
The image_tag accepts two parameters. A source, and a options Hash.
What you are trying to do is squeezing your return value from stop_data into this options Hash.
In order to get this to work, you first, need to return a Hash from stop_data, and second, make sure you pass only two arguments to image_tag - the source, and the options.
First:
def stop_data(order)
{
:class => tour_stops.find_by_order(order).name,
:data => { :order => order } # you may need order.to_json
}
end
Second:
link_to image_tag("new_button.png", tour.stop_data(1), :title => "Add new asset"), new_asset_path
This looks like it will work, but it won't, since your'e passing three parameters to image_tag.
When you do the following:
image_tag("new_button.png", :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset")
It looks like you're passing even 4 parameters to image_tag, but in fact they are only two. In Ruby, when the last parameter of a method is a Hash, you don't need to wrap the Hash key/value pairs in curly braces ({}), so the example above is essentially the same as
image_tag("new_button.png", { :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset" })
Now, to get your helper to work with image_tag, you need to merge the options, so they become only one Hash.
link_to image_tag("new_button.png", tour.stop_data(1).merge(:title => "Add new asset")), new_asset_path
Again, we're omitting the curly braces when calling merge, because it's only (and therefore last) parameter is a Hash. The outcome is the same as:
tour.stop_data(1).merge({ :title => "Add new asset" })

creating a model with name "import" is it reserved word in rails 3?

having all kind of strange stuff happening with a model and form named "import"
is this a reserved word in rails somehow? I could not find it in some old webposts on reserved words in rails.
EDIT:
Some code example to Illustrate, seem to be unable to pinpoint the problem
Works:
- #profile = Profile.new
= form_for #profile, :method => :get, :html => { :class => 'form-horizontal' } do |f|
throws error # embed raw
Fails:
- #import = Import.new
= form_for #import, :method => :get, :html => { :class => 'form-horizontal' } do |f|
With error:
undefined method `imports_path' for #<#<Class:0x007fe4e0369468>:0x007fe4e25410e0>
To my knowledge, import is not a reserved word in Ruby.
It is much more likely an issue with your specific codebase.
Solved it was incorrect naming of controller import model that caused this, I missed the S char in the filename

How to “dynamically add options” to 'form_for'?

I am using Ruby on Rails 3.2.2. In order to implement a "dynamic generated" AJAX style file upload form I would like to "dynamically add options" to the FormHelper#form_for statement if some conditions are meet. That is, at this time I am using code as-like the following (note that I am using the merge method in order to add options to the form_for method):
<%
if #article.is_true? && (#article.is_black? || && #article.is_new?)
form_options = {:multipart => true, :target => "from_target_name"}
else
form_options = {}
end
%>
<%= form_for(#article, :remote => true, :html => {:id => "form_css_id"}.merge(form_options)) do |form| %>
...
<% end %>
However, I think that the above code is too much hijacked.
Is there a better way to accomplish what I am making? For example, can I access from view templates some (unknown to me) instance variable named as-like #form and "work" on that so to change related options as well as I would like? Or, should I state a helper method somewhere? How do you advice to proceed?
BTW: Since the upload process is handled by using a HTML iframe, I am using the remotipart gem in order to implement the AJAX style file upload form - I don't know if this information could help someone...
This looks like a good candidate for a helper method. In your view:
<%= form_for(#article, :remote => true, :html => article_form_options(#article, :id => "form_css_id")) do |form| %>
...
<% end %>
In app/helpers/articles_helper.rb
module ArticlesHelper
def article_form_options(article, defaults = {})
extras = if article.is_true? && (article.is_black? || article.is_new?)
{ :multipart => true, :target => 'form_target_name' }
else
{}
end
defaults.merge(extras)
end
end
Helpers are a good place to keep logic that's too complex for a view but still related to the view.

Generating unique HTML ids in Rails when using a repeated partial that has form_for

I have a view on my current project which does something like the following(in haml):
-#horses.each do |horse|
= render :partial => 'main/votingbox', :locals => {:horse => horse}
The in the _votingbox.html.haml file I have the following:
%div.votingbox
%span.name= horse.name
%div.genders
- if horse.male
%img{:src => 'images/male.png', :alt => 'Male'}
- if horse.female
%img{:src => 'images/female.png', :alt => 'Female'}
%div.voting_form
= form_for(Vote.new, {:url => horse_vote_path(horse)}) do |f|
= f.label :comment, "Your opinion"
= f.text_field :comment
...
a bunch of labels and input elements follow generated using the form helpers
This will generate working code but it does generate forms with the same ids for all the form elements which makes the HTML invalid once the votingbox partial is rendered a second time.
My first guess at fixing this was to specify a unique :id to form_for but that only applies to the form tag generated by form_for and not any of the tags inside the form_for block.
One definite solution to this problem is to go through and manually define my own unique ids on form_for and all the form elements I use. This is more work than I had hoped for.
Is there an easier or cleaner way to get unique ids in a similar format to the way Rails currently generates them on all my form elements?
I have removed the original answer as it is totally irrelevant to the updated version of the question.
Update: So now we know that you have an unsaved ActiveRecord object passed to the form_for call, the answer becomes simple: You can override any parameter that form_for generates. That includes the element id. And fields_for sets the context for a specific record.
= form_for(Vote.new, :url => horse_vote_path(horse), :id => dom_id(horse, 'vote')) do |f|
= f.fields_for horse, :index => horse do |fh|
= fh.text_field :whatever
…
You can override the autogenerated ids and names of all form_for content with :as like the following:
= form_for(Vote.new, :as => horse.name, {:url => horse_vote_path(horse)}) do |f|
= f.label :comment, "Your opinion"
= f.text_field :comment
So if a given horse.name is foobar, it will generate a comment field whose id is foobar_comment and name is foobar[comment]
But remember to make sure that the dynamic parameter is acceptable as an html id, a horse.name like hor$e is not acceptable as an html id and therefore might break something.
P.S: Sorry for answering very late, but at the time the question was asked, I haven't had learnt anything at all about rails! hope that might help someone out there!

Resources