How do I create a form for an associated model? - ruby-on-rails

I have a company model and a bank_account model.
company has_many bank_accounts and bank_account belongs_to company.
I have a route companies/:company_id/bank_accounts/new which generates a form:
<%= form_for #bank_account do |form| %>
(form elements here)
<% end %>
But when I get to that page, I get: undefined method bank_accounts_path
Here's my resource routes in routes.rb:
resources :companies do
resources :bank_accounts, module: :companies
end
and my nested bank_account_controller.rb in controllers/companies/
I need my form to post the entered data to the create action. Ruby should know this already right because I'm in the new action? But clearly it doesn't recognise the route.
Let me know if you need more information.

So I was changing a few things to match a similar model for company contacts. I knew these we're the same concept in my application so the same routing and form should work.
First I moved my nested bank_account_controller.rb out of companies and just placed it in app/controllers.
I moved all my bank_account views out of the nested bank_account folder inside views/companies to just app/views/bank_accounts.
I then removed the module companies from my routes.rb so I just had resources :bank_accounts within my companies resources.
Finally, I changed the form_for to: form_with (model: [#company, #bank_account], local: true) do |form| %>
Forms constantly trip me up as a somewhat newbie to RoR. I need to understand better what the difference is between for and with :)

You have nested resource, therefore you need
<%= form_for [#company, #bank_account] do |form| %>

Related

Edit/create nested resources in Formtastic (Rails)

This question is regarding Rails 4/postgresql and the app is hosted on Heroku.
I am making a Quiz-functionality on a website and I am wondering on how to implement the forms (using Formtastic) best to make this is easy as possible. I have three models:
Quiz (has_many :quiz_questions), e.g. "Test to see how awesome you are"
QuizQuestion(belongs_to :quiz, has_many :quiz_options). e.g. "1. Which is your favorite color")
QuizOption (belongs_to :quiz_question). e.g. "Blue"
I have set up the forms like this:
<%= semantic_form_for([:admin, #quiz], :url => admin_quiz_path(#quiz.id)) do |f| %>
<%= render 'form' , :f => f %>
<% end %>
where the form looks like this:
<%= f.inputs %>
<h3>Quiz questions</h3>
<%= f.semantic_fields_for :quiz_questions do |qq_f| %>
<%= qq_f.inputs %>
<h4>Quiz options</h4>
<%= qq_f.semantic_fields_for :quiz_options do |qqo_f| %>
<%= qqo_f.inputs %>
<% end %>
<% end %>
<%= f.actions do %>
<%= f.action :submit %>
or go <%= link_to 'back', admin_quizzes_path %>
<% end %>
It seems, however, not to be working the way I want. I expect to be able to see the fields of QuizQuestion and QuizOptions in this form (there are objects for those) but I don't.
More importantly is that I would like to be able to create a New QuizQuestion and subsequently QuizOption in this form. It doesn't necessarily have to be jQuery/ajax or anything but I would like to do it all from this form.
Basically, I would like my workflow to be like:
Create a Quiz and add values to it. Click Create.
Add QuizQuestion number one and add the values to it (like "name label"). Click Create.
Add QuizOption related to QuizQuestion number one, and its "name label". Click create.
Repeat for QuizQuestion/QuizOption until the Quiz is done.
How can I do this?
For your workflow you might have to add accept_nested_attributes_for for the nested resources, this way when creating an object object you can actually create nested children (as long as they fulfill all the validations). This way:
# A quiz :has_many :quiz_questions
#quiz = Quiz.create(...)
with a declaration like:
has_many :quiz_questions
accepts_nested_attributes_for :quiz_questions
in your Quiz model you'll actually be able to create QuizQuestion from the quiz model like:
# using the previously quiz model
quiz.quiz_questions.create(...)
Doing the same for the deeply nested associations will do have the same effect.
Perhaps the reason why you don't see any field on the form is because there is not nested object created. Let me explain. When you create a new Quiz object, in your quizs_controller (or whatever the inflection for quiz is...) you need a:
def new
quiz = Quiz.new()
end
and
def create
Quiz.new(quiz_params)
end
private
def quiz_params
# whitelisted parameters sent along with the form
params.require(:quiz).permit(...)
end
if you actually want to be able to see the fields in the form you'll have to use the build method and actually populate that new object with respective the nested resources.
Note that for this to work with the form you will have to whitelist in the quizzes_controller the right attributes. You can debug the params you receive once you send the new quiz formulary and check that everything is right.
TIP! if you don't want to worry about the JS when adding nested resources dynamically, I recommend you using the cocoon gem

Use rails_admin forms in custom views?

I am making my own custom view that I need to make the process of creating associated models less painful for my users. I want to display all of the models associated pieces in-line, with controls to edit them. This is quite easy to roll my own for the basic fields, but I'd rather use a form_filtering_select partial for the inline model's associations, but I can't find any documentation to do this.
You can use Nested Form
Consider a User class which returns an array of Project instances from the projects reader method and responds to the projects_attributes= writer method:
class User
def projects
[#project1, #project2]
end
def projects_attributes=(attributes)
# Process the attributes hash
end
end
Note that the projects_attributes= writer method is in fact required for fields_for to correctly identify :projects as a collection, and the correct indices to be set in the form markup.
When projects is already an association on User you can use accepts_nested_attributes_for to define the writer method for you:
class User < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects
end
This model can now be used with a nested fields_for. The block given to the nested fields_for call will be repeated for each instance in the collection:
<%= nested_form_for #user do |user_form| %>
...
<%= user_form.fields_for :projects do |project_fields| %>
<% if project_fields.object.active? %>
Name: <%= project_fields.text_field :name %>
<% end %>
<% end %>
...
<% end %>
Here goes the Reference for details.
There's a cool gem out there that does pretty much what you want. It's called Nested Form Fields. It allows you to edit records (along with their has_many associations) on a single page. The cool thing about it is that it even uses jQuery to dynamically add/remove form fields without a page reload. Checkout out the gems docs for proper usage. Hope that helps!

Link To Parent From Nested Resource

How on earth do I link up to a parent resource? My Companies have many Orders.
In my orders view, I have listed the associated company with
#order.company.name
However, when I try and use link_to, it links only to the order:
<%= link_to #order.company.name, company_path %>
In my routes, I have this:
resources :companies do
resources :orders do
resources :comments
end
end
What's the fix and where can I read more about it?
<%= link_to #order.company.name, company_path(#order.company) %>
You have to pass something to company_path so that it knows which Company to get the path for. That is distinct form companies_path which returns the path for all the companies.
/companies/12
vs
/companies
I guess you have a model orders and a model companies. so companies has_many orders. If you setup this with the usual way your records are all have id as identifier. In this case company.id is the record id if you want to make a link back to the company page.

Mongoid embeds_one form_for path error for new objects

Can you have the same model class be a collection resource in one and a singular resource in the other?
UPDATE !!!
I think its a mongoid issue, as editing existing photos works. Only new throw the path errors
ORM is Mongoid beta 20
routes.db
resources :products do
resources :photos do
collection do
post 'sort'
end
end
end
resources :companies do
resource :photo
end
photos_controller.rb
before_filter find_or_build_photo
def find_or_build_photo
# these have many photos
if !params[:story_id].blank? or !params[:product_id].blank?
#photo = params[:id] ? #parent.photos.find(params[:id]) : #parent.photos.build(params[:photo])
end
# these have one photo
if !params[:company_id].blank?
#photo = #parent.photo ? #parent.photo : #parent.build_photo(params[:photo])
end
end
I get some "undefined method photo_path" etc. errors in the view with the form_for helper.
My Theorie -> because there is only a "photos"-controller and no "photo"-controller. this confuses the path-blackmagic!?
Started GET "/companies/4cf6b9c3499dda12e3000003/photo/edit" for 127.0.0.1 at Thu Dec 02 17:51:42 +0100 2010
Processing by PhotosController#edit as HTML
Parameters: {"company_id"=>"4cf6b9c3499dda12e3000003"}
mcu_dev['companies'].find({:_id=>BSON::ObjectId('4cf6b9c3499dda12e3000003')}, {}).limit(-1)
Rendered photos/_form.html.haml (3893.3ms)
Rendered photos/edit.html.haml within layouts/application (3899.1ms)
Completed in 6730ms
ActionView::Template::Error (undefined method `company_photos_path' for #<# <Class:0x103842e30>:0x1038404a0>):
1:
2:
3: = form_for [#parent, #photo], :html => { :multipart => true } do |f|
4: -if #photo.errors.any?
5: #errorExplanation
6: %h2= "#{pluralize(#photo.errors.count, "error")} prohibited this photo from being saved:"
app/views/photos/_form.html.haml:3:in `_app_views_photos__form_html_haml___1111817113_2176907420_506750'
app/views/photos/edit.html.haml:3:in `_app_views_photos_edit_html_haml__1185726823_2176970040_0'
lib/include/flash_session_cookie_middleware.rb:16:in `call'
when i debug it. the instance variables are set:
http://img4.imageshack.us/img4/6892/rubyerror.png
Full Source: github.com/banditj/mongoid-carrierwave-uploadify
Yes you can.
The reason you're getting the undefined method photo_path is because you're not using the nested resource that you have defined.
In your form_for you should be doing this:
<%= form_for [#company, :photo] do |f| %>
Where #company is a pre-existing company object.
Try overriding the url:
<%= form_for [#company, #photo], :url => company_photo_path(#company) do |f| %>
<% end %>
This ought to give you a form that POSTs to PhotosController#create. You probably want to do a PUT though, since your controller picks up the photo if it exists, in which case you also need to pass in :html => { :method => :put }, which should go to PhotosController#update.
The find_or_build_photo method is getting really smelly.
It feels like you are unnecessarily overloading the Photo model. A product having many photos is different than an avatar for the Company.
Plus Mongoid gets confused by the multiple embedded_in declarations found in Photo.
I would recommend creating a second model called Avatar for singular resource needs such as adding a photo to a Company or Person. Use Photo for multiple entries in Product or Story.
This is a better model of the real-world. It also allows setting different sizes for Avatar vs Photo. Typically I throw away the original and only make one or two small sizes in Avatar. For Photo I keep the original and make four or five different sizes for more flexible presentation in my stories.
Company would then embeds_one :avatar. Where Product would embeds_many :photos.
This clean separation of purpose should fix the problem with singular vs multiple resources in routes.
For Avatar, Uploadify is unnecessary. Just use a standard file upload form element. It's simple and can be added to the larger Company form.

Rails: how are paths generated?

In Rails 3, when a scaffold is generated for instance for a 'Category' the will be a categories_path (and a edit_category_path(#category), ...) used in the erb views.
This is not a variable that can be found anywhere and probably is generated. However in my case, for a different entity, Article, I first generated the model and then the controller. Now when I try output an articles_path, I get a
undefined method `articles_path' for #<#:0x000001019d1be0>
I cannot even use a <%= form_for(#article) do |f| %> as this generates the same error.
What am I supposed to do?
My routings are like this:
resources :categories do
resources :articles
end
The articles resource is within the categories scope, so the correct path to use would be category_articles_path(#category) or edit_category_articles_path(#category, #article). To do this for your form_for, try:
<%= form_for([#category, #article]) do |f| %>
As article lives in the category scope, you need to use category_articles_path.

Resources