undefined method `model_name' in a partial rendered by different controller - ruby-on-rails-3

I'm trying to render this form:
<form class="form-inline">
<%= simple_form_for #prospect,
:url => url_for(:action => 'create', :controller => 'prospects'),
:method => 'post' do |f| %>
<%= f.error_notification %>
<%= f.input :name, placeholder: 'Name', label: false %>
<%= f.input :email, placeholder: 'Email', label: false %>
<%= f.input :interests, placeholder: 'Tell us what you were searching for', label: false, value: params[:search] %>
<%= f.error :base %>
<%= f.button :submit, "Submit", :class=> "btn" %>
<% end %>
Using this partial:
<%= render partial: 'prospects/novideo_capture' %>
The partial is in a view controlled by Videos#index controller, and I keep getting this error: 'undefined method `model_name' for NilClass:Class'
This is my prospects controller:
class ProspectsController < ApplicationController
def index
#prospects = Prospect.all
end
def new
#prospect = Prospect.new
end
def create
#prospect = Prospect.new(params[:prospect])
if #prospect.save
render "thanks_for_interest"
else
render "novideo_capture"
end
end
I'm not sure what I'm going wrong, although I'm pretty sure it's a simple solution. I've seen a lot of similar questions around SO and tried all their answers, but none of them seem to work for this situation.
Thanks for any help...
EDIT: Adding
#prospect = Prospect.new
to the videos index controller stops the error occurring, but I don't feel it's the right way to do this. It also doesn't actually make the form use the prospects controller.
EDIT2: I now have the partial rendering correctly (I think), and my videos#index calls the partial like this:
<%= render partial: 'prospects/novideo_capture', :prospect => #prospect %>
Then simple_form in the partial looks like this:
<form class="form-inline">
<%= simple_form_for :prospect,
:url => url_for(:action => 'create', :controller => 'prospects'),
:method => 'post' do |f| %>
...
<% end %>
However it's not actually submitting the form with the prospects controller. Any ideas why?

Check your markup. You're wrapping a simple_form inside another form. Since the first form tag has no action associated with it (<form class="form-inline">), that form will submit against the current URL, which is the video#index.
You're going to want something like this:
<%= simple_form_for :prospect, :url => etc, :method => 'post', :class => "form-inline" do |f|
...
<% end %>
Losing the leading (redundant) form-inline form tag and you'll be fine.

Related

when using semantic_form_for accurs "ActionView::Template::Error (undefined method `my_leaders_path' for #<#<Class...)"

model:
class MyLeader < ActiveRecord::Base
extend Enumerize
belongs_to :interviewer
attr_accessible :interviewer_id, :is_leader, :content
enumerize :is_leader, :in => %w[yes no]
end
controller:
ActiveAdmin.register MyLeader, :namespace => :fieldwork do
form do |f|
render :partial => 'content'
end
end
rake routes:
batch_action_fieldwork_my_leaders POST /fieldwork/my_leaders/batch_action(.:format) fieldwork/my_leaders#batch_action
fieldwork_my_leaders POST /fieldwork/my_leaders(.:format) fieldwork/my_leaders#create
new_fieldwork_my_leader GET /fieldwork/my_leaders/new(.:format) fieldwork/my_leaders#new
edit_fieldwork_my_leader GET /fieldwork/my_leaders/:id/edit(.:format) fieldwork/my_leaders#edit
fieldwork_my_leader GET /fieldwork/my_leaders/:id(.:format) fieldwork/my_leaders#show
PUT /fieldwork/my_leaders/:id(.:format) fieldwork/my_leaders#update
DELETE /fieldwork/my_leaders/:id(.:format) fieldwork/my_leaders#destroy
_content.html.erb:
<div style="width:80%;margin-left:400px">
<%= semantic_form_for MyLeader.new do |f| %>
<%= f.input :interviewer_id, :as => :hidden%>
<%= f.input :is_leader%>
<%= f.actions do %>
<%= f.action :reset, :as => :button %>
<%= f.action :submit, :as => :button %>
<% end %>
<% end %>
The ERROR is:
ActionView::Template::Error (undefined method `my_leaders_path' for #<#<Class:0x007fadc5f8cdf0>:0x007fadc3d929e8>):
Why this happened: undefined method `my_leaders_path'?
should that be fieldwork_my_leaders_path?
Seems like your form cost you an issue.
Here is example from documentation.
Partials
If you want to split a custom form into a separate partial use:
ActiveAdmin.register Post do
form partial: 'form'
end
Which looks for something like this:
app/views/admin/posts/_form.html.arb
active_admin_form_for resource do |f|
inputs :title, :body
actions
end
This is a regular Rails partial so any template engine may be used.
Make sure that you put _content.html.erb in right folder.

ActiveAdmin - Pass locals to form

In my photos.rb file I have:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo', :locals => { :events => Event.all }
end
In my _photo.html.erb file I want to be able to access the value of events, but it doesn't seem to be detectable. How can I do this?
As requested in a comment, here is my form:
<% if events.any? %>
<%= form_for [:admin, #photo], :validate => true do |f| %>
<!-- insert a bunch of standard field divs here -->
<div class="actions" style="margin-top: 20px">
<% if #photo.new_record? %>
<%= f.submit 'Create photo' %>
<% else %>
<%= f.submit 'Update photo' %>
<% end %>
</div>
<% end %>
<% else %>
<div style="font-size: 14px">
You cannot add photos until you have added at least one event.
</div>
<% end %>
The error message I am getting is around the events.any? line:
Completed 500 Internal Server Error in 108ms
ActionView::Template::Error (undefined local variable or method `events' for #<#<Class:0x007fdb8e841b80>:0x007fdb8a93e7a8>)
form do |f|
f.render partial: 'admin/forms/photo', locals: { f: f, events: Event.all }
end
Note that you will need to remove form_for, semantic_form_for, active_admin_form_for etc from your partial, since it will be covered by the form do part in the admin/photos.rb, otherwise there will be two nested forms.
Example partial:
# app/views/admin/forms/_photo.html.arb
if events.any?
f.inputs do
f.input :title, label: 'Etc'
f.input :file
end
f.actions
else
f.div 'You cannot add photos until you have added at least one event.',
style: 'font-size: 14px'
end
form do |f|
render partial: 'admin/forms/photo', locals: { value: 'random_data' }
end
You can use f.render or just render.
Note that partial: is required to send locals to the form
Example Partial
#app/views/admin/forms/_photo.html.arb
active_admin_form_for [:admin, resource] do |f|
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :name
f.input :random if (value == 'random_data')
end
f.actions
end
another thought on this, if you want to check only if there are any Events in db you can make any call directly on Class:
<% if Event.any? %>
do this
<% else %>
do that
<% end %>
without sending variables to partial, the above code result in:
2.0.0p0 :004 > Event.any?
(0.6ms) SELECT COUNT(*) FROM "events"
=> true
and leave the ActiveAdmin partial without locals:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo'
end

Does a Rails plugin exist to build a show page (like a formbuilder)

I'm looking for a Rails plugin providing a builder for show.html.erb pages.
For example, with SimpleForm, an new.html.erb page might look like this :
<%= simple_form_for(#user, :url => user_registration_path, :html => ... }) do |f| %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
...
<% end %>
But I was not able to find an equivalent for just displaying fields.
A generated show.html.erb page looks like :
<p>
<b>Email:</b>
<%= #user.email %>
</p>
...
But I'd like something like :
<%= simple_display_for(#user, :html => ... }) do |d| %>
<%= d.output :email %>
<%= d.output :name %>
...
<% end %>
Does this kind of builder exist?
Thanks
EDIT : If the builder use Twitter Bootstrap, that's even better :)
I don't know of any gems, but here is a simple example of how to build this feature yourself, which you can expand on:
lib/simple_output.rb
class SimpleOutput
def initialize(resource)
#resource = resource
end
def output(attribute)
#resource.send attribute
end
end
config/initializers/simple_output.rb
require_dependency 'lib/simple_output'
helpers/simple_output_helper.rb
module SimpleOutputHelper
def simple_output_for(resource, options={}, &block)
content_tag :div, yield(SimpleOutput.new(resource)), options[:html] || {}
end
end
users/show.html.erb
<%= simple_output_for(#user, html: { style: "background-color: #dedede" }) do |r| %>
<%= r.output :name %>
<%= r.output :email %>
<% end %>
Now, obviously this is just a very simple example, but hopefully it will get you started on the right track. Look at the simple_form source to see how they organize their code, and how they "typecast" fields. The simple_form codebase is very clean and easy-to-follow Ruby, and is a great example of what a gem should look like.

Rails Form In General Layout

I'm know this is a newbie question just not sure what I'm missing and decided to post hear after my usual search through Google. I'm trying to post content to the database from a form in the footer of the application (for a newsletter) the view is therefore repeated throughout the application. Right now when I submit the form a new object is created in the database but all the fields are "NULL". It seems I need to put the #newsletter variable somewhere, I'm just not sure where.
Partial I'm Rendering in the View
<%= form_tag({:controller => "newsletters", :action => "create"}, :method => "post", :id => "footer_email_form") do %>
<%= text_field_tag :first_name, '', id: "footer_email_firstname" %>
<%= text_field_tag :last_name, '', id: 'footer_email_lastname' %>
<%= text_field_tag :email, '', id: 'footer_email_address' %>
<%= submit_tag "Submit", :name => nil, id: 'footer_email_submit', class: "btn btn-primary" %>
<% end %>
Controller (Create Action)
class NewslettersController < ApplicationController
def create
#newsletter = Newsletter.new(params[:newsletter])
if #newsletter.save
format.html { redirect_to 'pages#home', notice: 'Thank You for signing up for our newsletter' }
format.json { render json: #newsletter, status: :created, location: #newsletter }
else
format.json { render json: #newsletter.errors, status: :unprocessable_entity }
end
end
end
Routes
resources :newsletters, :only => [:create, :destroy]
Use something like this:
<%= form_for Newsletter.new do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_field :email %>
<%= f.submit_tag "Submit", class: "btn btn-primary" %>
<% end %>
The way your original form works the params are submitted like this:
params = {
:first_name => 'A',
:last_name => 'B',
:email => 'C',
# and so on...
}
Now if you do #newsletter = Newsletter.new(params[:newsletter]) nothing will happen, because params[:newsletter] is nil and therefore all your attributes are going to be nil (and show up as NULL in the DB).
You should always have an eye on the development log. It's going to help you debug such errors.

Rails appends id to singular route when render edit after errors

I have the following singular route:
scope '/seller' do
resource :seller_profile, :path => "/profile", :only => [:show, :edit, :update]
end
and the following controller:
class SellerProfilesController < ApplicationController
before_filter :validate_user_as_seller
def show
#seller_profile = current_user.seller_profile
end
def edit
#seller_profile = current_user.seller_profile
end
def update
#seller_profile = current_user.seller_profile
if #seller_profile.update_attributes(params[:seller_profile])
redirect_to(seller_profile_path, :notice => 'Profile was successfully updated.')
else
render :action => "edit"
end
end
end
I use a singular route given that the user must be authenticated before gaining access to the controller and therefore I can get the seller_profile from the user logged in.
This works like a charm, with only one problem. When I edit the seller_profile and validation error happen, the form is edited again and the errors are displayed correctly. The problem is that rails appends to the url the id of the edited record. For instance,
when I first edit the record, the url is:
http://0.0.0.0:3000/seller/profile/edit
but if the form is submitted with validation errors, the form itself is redisplayed under
http://0.0.0.0:3000/seller/profile.2
where 2 is the ID of the record being edited.
The form is the following:
<%= simple_form_for #seller_profile do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>
Everything, as said, works great but I would totally mask the ID in the url. What should I do?
I have not really worked too much with simple_form_for. But it looks like it is guessing your url always as if they were not single resources. You can provide a custom one:
<%= simple_form_for #seller_profile, :url => seller_profile_path do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>