I'm making a mailer so that I have a business directory, each business listing has a form and when the form is filled out and submitted it is sent to the relative business email with the lead information.
Here's the mailer folder file:
class Enquiry < ActionMailer::Base
default from: "admin#uk-franchise.co.uk"
attr_accessible :name
def lead(listing)
#listing = listing
mail(to: #listing.leadrecepient, subject: "test")
end
end
Here's the listing controller where I'm calling it:
def lead
listing = Listing.find(params[:id])
Enquiry.lead(listing).deliver
redirect_to listing
end
The view:
<%= form_for #listing, url: lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
The routes:
resources :listings do
member do
put :lead
end
end
And the error :(
undefined method `name' for #<Listing:0x4d7c6d8>
On the view line:
<%= listing.text_field :name %>
Any help greatly appreciated, mailers are a nightmare!
When you use form_for helper, it actually rely on a model object. Doing this, when you write listing.text_field :name it will actually look for a field name in the listing model. You get that error because your model (connected to a DB table? we would like to see the listing class) doesn't have this field. I can see it in the Enquiry class.
I would say you have to move it in the model, but is hard to say without seeing the Model or knowing for what you need that field...
Show us the model and explain a little better what are you trying to do, so we can help you :)
Related
I have a User model which is working under Devise with no problems (using devise sanitizer to update fields, so no UsersController)
I am working on creating a Quiz model, which belongs_to the User model, and the User model has_one Quiz. In my routes, I have: resources :users, :quizzes (is this supposed to be quizzes or quizs? I know that Rails pluralizes but couldn't seem to find which it'd be in this case).
In my views, I'm trying to open up a modal (which works) and inside have it populated with fields that a User can enter in questions they want (q1 through q5 being the database fields).
Inside the modal content area, I have the code:
<%= form_for #quiz, url: {action: "new"} do |f| %>
<%= f.submit "Create" %>
<% end %>
and I get the error "First argument in form cannot contain nil or be empty"
Inside my quizzes controller, I have defined new as
def new
#quiz = Quiz.new
end
I would greatly appreciate some assistance here! Thank you.
In your WelcomeController action: index add this line to initialized #quiz
def index
#quiz = Quiz.new
end
hope you made a good progress in your project.
shoudn't it be like following
<%= form_for #quiz do |f| %>
<%= f.submit "Create" %>
<% end %>
I have a Books model and it has CRUD operations. In config/routes.rb, I have declared
map.resources :books
My new.html.erb looks like as:
<%= form_for :book, url: books_path do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.submit :Add %>
<% end %>
My create method in controller looks like as:
def create
book = Book.new(authorized_params)
book.save
end
So, when I submit my form from views, request would go to the 'create' method and an record for the book gets created in database. Fair enough. Now, I want to have an edit page for book. So, my edit method in controller look like as:
def edit
#book = Book.find_by(params[:id])
render :new
end
When I go to my edit view, it automatically show the value of title in the text box, which is what I expected.. But when I try to submit the form again(ofcourse after changing the title value) it again creates a new record instead of updating it..
Something basic which I missed out in my reading? I googled about it though but did not find satisfactory answer.
The issue is that you are using the 'new' view where form has the post method. If you will check the generated routes, post will be for create method, that is adding a new record. You will have to create a new view for edit where the form target URL will be edit_book_path(#book) and method will be patch. Patch method will route to 'update' function in your controller where you will call #book.update. I am not writing the exact code, but these directions should help you achieve what you want
I have tried to create a mailer using the following code:
routes code
resources :listings do
member do
put :lead
end
end
mailer controller code
def lead(listing)
#listing = listing
mail(to: #listing.leadrecepient, subject: "test")
end
standard controller code
def lead
Enquiry.lead(#listing).deliver
end
view
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
In the context of a business directory, I want it so that there is a enquiry form on each listing page that when filled out and submitted, the information is sent to the relative listing email.
The problem however is that when I type into the form and click submit, I get the following error:
param is missing or the value is empty: listing
This seems to be because I have it in the "listing" controller which controls the showing and creation of the business listing itself. I therefore have strong params for a new listing which contains all the new listing variables:
def listing_params
params.require(:listing).permit(:fullname, :jobtitle, :email, :franchisename, :leadrecepint, :shortdescription, :longdescription, :website, :branchcount, :scale, :mininvestment, :investmentrange, :category, :hexbg, :logourl, :facebook, :twitter, :linkedin, :googleplus, :approved)
end
How do I go about fixing this? I'm a beginner if I'm honest, could really do with some help to get this mailer working! Thanks.
Strong params are for when you are submitting new resources or modifications to resources. To protect against people adding extra parameters that may circumvent security or other aspects of your application unexpectedly.
If you are adding an action to an existing resource that the user is authorized to access, which this appears to be, you want to just find the object by ID, and use it. So instead of finding it using the params filtered through listing_params, just find it like this in the controller:
def lead
listing = Listing.find(params[:id])
Enquiry.lead(listing).deliver
redirect_to listing
end
And invoke it using a simple link, instead of this:
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
Just use this in your view:
= link_to 'Go!', lead_listing_path(#listing), method: :put
Nothing more to it.
I have the following set of routes in my rails app:
resources :customers do
resources :jobs
end
I also have the following two models - job.rb and customer.rb:
class Job < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_many :jobs
end
I have the following New method in my jobs_controller.rb:
def new
#customer = Customer.find(params[:customer_id])
#job = #customer.jobs.build
end
I am trying to pass the customer ID directly to a new job upon creation, as every job should be associated with a customer (no rogue jobs with no customer_id associated).
In order to do that, I have the following link on the customer view page:
<%= link_to "Add New Job", new_customer_job_path(#customer) %>
When clicked, the ID is passing, but I am getting a no method error as follows:
NoMethodError in Jobs#new
undefined method `jobs_path' for #<#<Class:0x007f89899d9030>:0x007f898a7ab0f0>
<%= form_for(#job) do |f| %>
So it seems like some conflict with my routes as it does not like my jobs path - anyone know where this is coming from?
Thanks in advance for the help.
form_for #job will look for a jobs controller. Because you've nested it it won't work.
Switch it to
<%= form_for([#customer, #job]) do |f| %>
Assuming you have a before filter to find the customer in your controller.
Just replace
<%= form_for(#job) do |f| %>
to
<%= form_for[#customer, #job]) do |f| %>
I'm using Rails 2.3.2, and trying to get a nested object form to work properly. I've narrowed my problem to the issue that Rails is not setting my nested form elements with the *_attributes required to initiate the accepts_nested_attributes_for processing.
My model code is:
class Person < Party
has_one :name, :class_name => "PersonName"
accepts_nested_attributes_for :name, :allow_destroy => true
end
class PersonName < ActiveRecord::Base
belongs_to :person
end
My view code looks like this (I'm using HAML):
%h3 New customer
= error_messages_for :person, :person_name, :name, :country
- form_for :person, :url => collection_url, :html => {:class => 'MainForm'} do |person_form|
- #person.build_name unless #person.name
- person_form.fields_for :name do |name_form|
= name_form.label :given_name, "First Name:"
= name_form.text_field :given_name
= name_form.label :family_name, "Last Name:"
= name_form.text_field :family_name
= hidden_field_tag :inviter_id, params[:inviter_id]
= hidden_field_tag :inviter_code, params[:inviter_code]
%p= submit_tag "Create"
= link_to 'Back', collection_url
Instead of params being:
{"person"=>{"name_attributes"=>{"given_name"=>"Fred", "family_name"=>"Flintstone"}}, ...}
I get:
{"person"=>{"name"=>{"given_name"=>"Fred", "family_name"=>"Flintstone"}}, ...}
As a result, I get a TypeMismatch exception. I've followed the documentation from Ryan Daigle. I've also followed the advice from this blog and the complex-forms-example.
Using Firebug, I went through my form and adjusted the name attribute of the input tags from name to name_attributes. This produced the params with name_attributes, and the create worked fine.
I'm stuck as I cannot figure out why my form is not producing the *_attributes form of the name.
Another thing I tried is I got the complex_form_example working in my environment. I've gone through every inch of the controller, models and views and compared it to my code. I cannot find what is different. I know this is something small, and would appreciate any help!
Thanks!
Post backs do not get routed to the right place
def new
#person = Person.new
end
<% form_for #person do |f| %>
<% f.fields_for :name_attributes do |p| %>
...
<% end %>
<% end %>
Post backs get routed to the right place
def new
#person = Person.new
#person.name = PersonName.new # << this allows fields_for :relation vs :relation_attributes
end
<% form_for #person do |f| %>
<% f.fields_for :name do |p| %>
...
<% end %>
<% end %>
No need to #person.name again in #create
Try to use an actual object for form_for:
form_for :person => form_for #person
I have just been struggling for about an hour with exactly the same problem!
Follow nowk's pattern for the new method in the controller, then put this in your view
<% form.fields_for :name, #person.name do |name_form| %>
<% end %>
Good luck if you try it, that's what worked for me.
Not sure why this isn't working for, but as a workaround, you could just use params[:name] in your controller#create method to update the person record.
person = Person.new(params[:person])
person.name << PersonName.new(params[:name])
Unfortunately, I still have not been able to figure out why this form wouldn't work with nested object forms. I stripped it down to the simplest data, started over using the complex-form-example as a start. I ended using the active_presenter to gather x-object data from the form. I'll revisit nested object forms sometime in the form. Thanks for your help.
Thought I would share my solution as it's slightly different - in my case I want the nested attributes to be dynamic.
In new action:
case params[:type]
when "clubber"
#account = resource.send "build_#{params[:type]}"
when "promoter"
#account = resource.send "build_#{params[:type]}"
when "company"
#account = resource.send "build_#{params[:type]}"
when "venue_owner"
flash[:notice] = 'We ask that venue owners register via the web. Thanks.'
redirect_to root_path and return
end
In my view:
= f.fields_for #account.class.name.downcase+'_attributes' do |form|
Pretty ghetto, but it works.