I have the following model:
class Contact
attr_accessor :name, :emails, :message
def initialize(attrs = {})
attrs.each do |k, v|
self.send "#{k}=", v
end
end
def persisted?
false
end
end
I am calling to a contact form in my view like so:
<div class="email_form">
<%= render 'form' %>
</div>
Here is the controller:
class ShareController < ApplicationController
layout "marketing_2013"
respond_to :html, :js
def index
#contact = Contact.new
end
end
Here is the Form:
<%= form_for(#contact) do |f| %>
<%= f.label :name, "Your Name" %>
<%= f.text_field :name %>
<%= f.label :text, "Send to (separate emails with a comma)" %>
<%= f.text_field :emails %>
<%= f.label :message, "Email Text" %>
<%= f.text_area :message %>
<%= f.submit %>
<% end %>
For some reason I keep getting this error:
undefined method model_name for Contact:Class
Any reason why what I have currently wouldn't work?
Besides the correct route in your config/routes.rb, you will also need these two instructions on your model:
include ActiveModel::Conversion
extend ActiveModel::Naming
Take a look at this question: form_for without ActiveRecord, form action not updating.
For the route part of these answer, you could add this to your config/routes.rb:
resources :contacts, only: 'create'
This will generate de following route:
contacts POST /contacts(.:format) contacts#create
Then you can use this action (contacts#create) to handle the form submission.
add include ActiveModel::Model to your Contact file
your route probably doesn't go where you think it's going and therefore #contact is probably nill
run "rake routes" and check the new path.. if you are using defaults, the route is
new_contact_path.. and the erb should be in file: app/views/contacts/new.html.erb
def new
#contact = Contact.new
end
Related
I am trying to make a contact me form in Rials 5 with the built in Mail features.
I put it together a lot like a regular controller and views with a Mailer as the model. But when I have it all written out I get the error:
undefined method `model_name' for #ContactMailer
Contact is the name of the Mailer.
The error comes up when I try to view the new.html.erb page with rails server running. It looks like this:
Screen Shot
Here is the code I am working with:
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = ContactMailer.new
end
def create
#contact = ContactMailer.new(params[:name, :email, :message])
if #contact.deliver
flash[:success] = "Your message has been sent."
else
flash[:error] = "There was a problem sending your message."
render 'new'
end
end
And
new.html.erb
<%= form_for #contact do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control', required: true %></div>
<div class="form-group">
<%= f.label :message %>
<%= f.text_area :message, class: 'form-control' %>
</div>
<%= f.submit "Send", class: 'btn btn-default' %>
<% end %>
There is also the generated Mailer and views, but I have not changed anything with those.
From what I have been able to research the error could be that I have not initialized the #contact variable, but I believe that I have. And now I am lost. Any help would be appreciated.
As additional information:
My plan is for this contact form to send an email using send grid on Heroku.
You are trying to build a mailer.Thats not how they are used. They are not models.
Instead you would do something like:
ContactMailer.some_method_you_added_to_your_mailer(params[:name, :email, :message]).deliver_now
You don't use new on them.
Suggest you read over http://guides.rubyonrails.org/action_mailer_basics.html .
I have a user model which contains an "email switch" column with a boolean value. I'd like to create a button in my view which allows the user to turn "on" and "off" their emails. I can't get the submit button to update the value in the User model.
<%= form_for :user do |f| %>
<label>On</label>
<%= f.radio_button :email_switch, true %>
<label>Off</label>
<%= f.radio_button :email_switch, false %>
<%= f.submit "Save", :controller => "dashboard_emails", :action => "update", :method => "put" %>
<% end %>
class DashboardEmailsController < ApplicationController
before_filter :require_user
def index
end
def update
end
private
def require_user
#user = #logged_in_user
end
class User
field :email_switch, type: Boolean, default: false
end
You need to pass the arguments to form_for not to the f.submit call. If you have a persisted user assigned to #user you should be able to do:
<%= form_for #user do |f| %>
<label>On</label>
<%= f.radio_button :email_switch, true %>
<label>Off</label>
<%= f.radio_button :email_switch, false %>
<%= f.submit "Save" %>
<% end %>
Of course you need resources :users in your config/routes.rb to get this working. This should then send a PUT request to /users/47, which in turn fires the #update action of your UsersController
I have a form to create adverts.
Controllers:
def edit
#engines = Engine.all
#car = Car.find(params[:id])
end
def update
#car = Car.find(params[:id])
if #car.save
redirect_to root_path
end
end
My routes:
resources :adverts
Create.html.erb
<%= form_for #car, :url => adverts_path do |f| %>
<div><%= f.label :name %><br />
<%= f.text_field :name %></div>
<%= hidden_field_tag :model_id, params[:model_id] %>
<%= select_tag :engine_id, options_from_collection_for_select(#engines, "id", "name",:selected=>#car.engine_id) %>
<div><%= f.submit "Create car!" %></div>
<% end %>
I can create advert, but I can't to update it.
edit.html.erb
<%= form_for #car, :url => adverts_path do |f| %>
<div><%= f.label :name %><br />
<%= f.text_field :name %></div>
<%= hidden_field_tag :model_id, params[:model_id] %>
<%= select_tag :engine_id, options_from_collection_for_select(#engines, "id", "name",:selected=>#car.engine_id) %>
<div><%= f.submit "Update car!" %></div>
<% end %>
when I submited my form, I have an error - No route matches [PUT] "/adverts"
$ rake routes:
adverts GET /adverts(.:format) adverts#index
POST /adverts(.:format) adverts#create
new_advert GET /adverts/new(.:format) adverts#new
edit_advert GET /adverts/:id/edit(.:format) adverts#edit
advert GET /adverts/:id(.:format) adverts#show
PUT /adverts/:id(.:format) adverts#update
DELETE /adverts/:id(.:format) adverts#destroy
I need help.
When you are updating you have to let Rails know which object you want to update by passing an id.
In edit.html.erb change:
<%= form_for #car, :url => adverts_path do |f| %>
to:
<%= form_for #car, :url => advert_path(#car) do |f| %>
By the way, I find your code very strange. Why don't your model names match your controllers and routes? I mean you are creating an advert but your model is called car. That doesn't make any sense. Either call it car or advert, but don't mix them.
If you used RESTful routing, you don't need to specify a url, just need:
<%= form_for #car do |f| %>
The form can know #car is new record, or saved record, so it will send appropriate http method.
And in your update action:
def update
#car = Car.find(params[:id])
if #car.update_attributes(params[:car])
redirect_to root_path
end
end
I got myself in a similar situation today with a mismatched resource and model name. I agree the model and controller names need to correlate, but you can override the routes name to be whatever you want.
resources :cars, path: "adverts"
Along with RESTful routing
<%= form_for #car do |f| %>
You may also want to make sure your url: path is singular on the #form_form.
I have a project that contains projects that have todos that have tasks. When I try to create a new task, I get this error when I submit:
No route matches [POST] "/projects/1/todos/19/tasks/new"
Here is my form:
<%= form_for [#todo, #todo.tasks.new], :url => new_project_todo_task_path(#project, #todo) do |f| %>
<div class="field">
<%= f.label :description, "Description" %><br />
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %> or <%= link_to "Cancel", "#", :id => "cancel_new_task_link" %>
</div>
<% end %>
Here is my controller:
class TasksController < ApplicationController
before_filter :authenticated?
before_filter :get_project_and_todo
respond_to :html, :xml, :json, :js
def new
#task = #todo.tasks.new
end
def create
#task = #todo.tasks.new(params[:task])
if #task.save
respond_with #todo, :location => project_todo_path(#project, #todo)
else
render "new"
end
end
private
def get_project_and_todo
#project = Project.find(params[:project_id])
#todo = #project.todos.find(params[:todo_id])
end
end
Here are my routes:
resources :projects do
resources :todos do
resources :tasks
end
end
Thanks
Your URL should not be new_project_todo_task_path(#project, #todo). You don't need to specify the URL here as Rails will imply it from the parameters passed in to form_for.
If the final object is a new object and not persisted in the database then it will make a POST request to, in this case, /projects/:project_id/todos. You're declaring in your example that you want to make a POST request to /projects/:project_id/todos/new, for which there is no POST route and that is why it's failing.
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 %>