I am uploading an image and want to associate it with the current project I'm in. I'm inside a project at the URL example.com/projects/1 and render this form:
<%= semantic_form_for #image, :html => { :multipart => true } do |f|%>
<%= f.semantic_errors %>
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :description %>
<%= f.input :image, :as => :file %>
<% end %>
<%= f.buttons do %>
<%= f.commit_button :label => 'Upload Image', :button_html => { :class => "btn primary" } %>
<% end %>
<% end %>
I've set in image.rb model, belongs_to :project and in project.rb model, has_many :images
My images_controller.rb create method looks like this:
def create
image = params[:image]
if user_signed_in?
#image = Image.new(:title => image[:title],
:description => image[:description],
:user_id => current_user.id,
:project_id => params[:id])
if #image.save
flash[:success] = "Successfully uploaded an image"
redirect_to project_path(params[:id]) and return
else
flash[:error] = "Error with image upload"
redirect_to new_image_path and return
end
else
redirect_to root_path
end
end
The image is created but fails to associate the image with the project_id. I know the problem is with params[:id] not pulling in the project_id, how do I pull the project id from the URL and associate it with the image?
You should use your associations to create the new Image.
#image = Project.find(params[:id]).images.create(:title => image[:title],
:description => image[:description],
:user => current_user)
if #image.save...
if that does not work, please post the contents of your routes.rb and the url that is hit from the post request.
Related
I have a User model and a Company model linked like this:
class User < ActiveRecord::Base
belongs_to :company
accepts_nested_attributes_for :company
end
class Company < ActiveRecord::Base
has_many :users
end
On the sign in page, I want the user to set up both his info (mail, password) and his company info (several fields). So my form looks like this:
<%= simple_form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :email, :required => true, :placeholder => "user#domain.com" %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<h2>Company info</h2>
<%= simple_fields_for :company, :html => { :class => 'form-horizontal' } do |fa| %>
<%= fa.input :name %>
<%= fa.input :url %>
<%= fa.input :description, :as => :text, :input_html => { :cols => 60, :rows => 3 } %>
<%= fa.input :logo %>
<%= fa.input :industry %>
<%= fa.input :headquarters %>
<% end %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
root_url, :class => 'btn' %>
</div>
<% end %>
My user model has a company_id:integer field. So logically, when I sign in the user, the first thing to do is to create the Company before the User and then give to the user creation model the appropriate company_id. So I wrote this:
class UsersController < ApplicationController
before_create :create_company
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "Registration successful."
else
render :action => 'new'
end
end
private
def create_company
#company = Company.new(params[:company])
if #company.save
self.company_id = #company.id
else
render :action => 'new'
end
end
end
Problem is: when accessing /users/new I get this error:
undefined method `before_create' for UsersController:Class
What's going wrong? I checked, before_create has not been deprecated, I'm in Rails 3.2.8. This is probably something stupid with my create_company method but I can't figure why...
Thanks a lot for helping!
before_create is a hook method belonging to ActiveRecord
before_filter is a hook method belonging to Controller.
so I suggest you to re-build your code after you make clear which is which. ^_^
I have a form wizard setup with 4 steps that all work on the same model.
When I fill out the first one and click submit (and am redirected to step 2) the form is already filled out and a duplicate, identical form added below. This happens for each step.
How can i render a completely new form after i click submit on step 1 and am taken to 2 (or 3/4)?
step 1
<%= simple_form_for #user, url: wizard_path do |f| %>
<h2 class="signup">Step 3: Friends Birthday</h2>
<%= f.simple_fields_for :events do |event_f| %>
<%= event_f.input :name, :placeholder => 'Enter Persons Name' %>
<%= event_f.input :date, :as => :date_picker, :input_html => { :class => 'special' } %>
<%= event_f.input :reccuring, :label => false, :inline_label => 'Remind me of this event every year?' %>
<h3>Choose up to 3 interests for this person</h3>
<%= event_f.association :interests, :label => false, :as => :check_boxes %>
<%= event_f.input :kind, :as => :hidden, :input_html => { :value => "Birthday" } %>
<%end%>
<%= link_to "skip this step", next_wizard_path %>
<%= f.button :submit, 'Submit' %>
<%end%>
step 2
<%= simple_form_for #user, url: wizard_path do |f| %>
<h2 class="signup"> Married? Add your anniverarsy</h2>
<%= f.simple_fields_for :events do |anniversary_f| %>
<%= anniversary_f.input :name %>
<%= anniversary_f.input :date, :as => :date_picker, :input_html => { :class => 'special' } %>
<h3>Choose up to 3 interests for this person</h3>
<%= anniversary_f.association :interests, :as => :check_boxes, :label => false %></li>
<%= anniversary_f.input :kind, :as => :hidden, :input_html => { :value => "Anniversary" } %>
<%end%>
<%= link_to "skip this step", next_wizard_path %>
<%= f.button :submit, 'Submit' %>
<%end%>
Controllers
events_controller.rb
def new
#user = current_user
#event = Event.new
end
def create
#user = current_user
#event = Event.new(params[:event])
#event.user = User.find(current_user.id)
end
users_controller
class UsersController < ApplicationController
before_filter :authenticate_user!
def create
#user = User.new(params[:user])
if #user.save
redirect_to user_steps_path
else
render :new
end
end
When you complete one step then intilize new object and bind this second form to new object.Repeat this step for 3rd and 4th form.
Mean every time initilize
#user = User.new
Bassicaly my problem what to do if i have 3 forms and one submit button.
I want to create a form which sends email to each recipient and then create new record in free_registration_coupons table.
I need validation of email for this form.
Model FreeRegistrationCoupon: recipient_email, token, sender_id
For now i have this:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = [params[:recipient_email_1], params[:recipient_email_2], params[:recipient_email_3]]
emails.reject!{ |e| e.eql?("") }
if emails.present?
emails.each do |e|
FreeRegistrationCoupon.create(:recipient_email => e, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
redirect_to(:back)
end
end
end
class FreeRegistrationCoupon < ActiveRecord::Base
before_save :generate_token
attr_accessor :recipient_email, :sender_id
validates :recipient_email, :presence => true, :email => true
def generate_token
self.token = SecureRandom.hex
end
end
This is form which is in other controller CarsController#confirm:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<!-- errors -->
<%= label_tag :recipient_email_1 %>
<%= text_field_tag :recipient_email_1 %>
<%= label_tag :recipient_email_2 %>
<%= text_field_tag :recipient_email_2 %>
<%= label_tag :recipient_email_3 %>
<%= text_field_tag :recipient_email_3 %>
<%= submit_tag %>
<% end %>
I think you should have defined your form using:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<%= #error_message %>
<%= label_tag "recipient_email[1]" %>
<%= text_field_tag "recipient_email[1]" %>
<%= label_tag "recipient_email[2]" %>
<%= text_field_tag "recipient_email[2]" %>
<%= label_tag "recipient_email[3]" %>
<%= text_field_tag "recipient_email[3]" %>
<%= submit_tag %>
<% end %>
This way it will be easier to treat all email address on your controller and you can track those errors to display them afterwards:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = params[:recipient_email]
emails.reject!{ |param, value| value.eql?("") }
errors = []
if emails.any?
emails.each do |param, value|
validation_result = FreeRegistrationCoupon.save(:recipient_email => value, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
#error_message = "You have to include, at least, one e-mail address!"
render :name_of_the_action_that_called_send_invitations
end
end
end
I didnt test this code. Hope it helps!
I have a partial that contains a form:
<% form_for :message, :url => { :action => "create" }, :html => { :id => 'form' } do |f| %>
<%= f.error_messages %>
<%= f.label :title, "title" %>
<%= f.text_field :title %>
<%= f.label :tag, "tag" %>
<% if controller.controller_name == "tags" %>
<%= f.text_field :tag_list, :value => #title %>
<% else %>
<%= f.text_field :tag_list %>
<% end %>
<%= f.label :name, "name" %>
<%= f.text_field :name %>
<%= f.label :email, "email" %>
<%= f.text_field :email %>
<%= f.label :title, "message" %>
<%= f.text_area :content %>
<%= f.submit 'submit' %>
<% end %>
I'm using this in two controllers: messages and tags. It works fine in the messages controller but not in the tags controller. When it's rendered in tags#show it autofills the tag field. When a message is submitted from tags#show I'm redirected to the root of the website with a flash error "Tag does not exist."
tags controller:
class TagsController < ApplicationController
before_filter :redirect_if_doesnt_exist#, :only => :show
def show
#title = Tag.find(params[:id]).name
#tag = Tag.find(params[:id])
#entries = Entry.paginate(Entry.find_tagged_with(#tag),
:page => params[:page], :per_page => 10, :order => "name")
#messages = Message.paginate(Message.find_tagged_with(#tag),
:page => params[:page], :per_page => 10, :order => "updated_at DESC")
#related_entries = Entry.tagged_with(#tag, :on => :tags)
#related_tags = #related_entries.collect{|x|x.tags}.flatten.uniq
#related_tags.delete(#tag)
end
private
# Redirect if requested tag does not exist
def redirect_if_doesnt_exist
#tag = Tag.find(params[:id]) rescue nil
if #tag.nil? # maybe "or #tag.empty?" could solve the empty tag issue
flash[:error] = 'Tag does not exist.'
redirect_to '/'
end
end
end
In case it isn't clear: The partial is shown in the view, the form within it just doesn't submit the data from the tags controller and is redirected. The partial works fine from the messages controller. This is a Rails 2.3.x application.
Thank you for reading my question, your time is appreciated.
Your problem is the URL of the form partial is only the action:
<% form_for :message, :url => { :action => "create" }, :html => { :id => 'form' } do |f| %>
If you include this in a view that isn't under messages_controller, it'll call the wrong action. If you include this ina a tags view, it'll try to call the create action for tags_controller instead.
It'll probably work if you just add the controller too:
<% form_for :message, :url => { :controller => :messages, :action => :create }, :html => { :id => 'form' } do |f| %>
Ok so I am having a problem with doing multiple forms in rails. here is the code below
Models
class Profile < ActiveRecord::Base
belongs_to :user
has_attached_file :avatar, :styles => { :medium => "134x137>", :thumb => "111x111>", :tiny => "32x38>" }
validates_attachment_content_type :avatar, :content_type => ['image/pjpeg','image/jpeg', 'image/x-png', 'image/png', 'image/gif']
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
Profile Controller
def edit
#user = User.find(params[:id])
#profile = #user.profile
end
Profiles Edit View
<% form_for #user do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.password_field :password_confirmation %>
<input id="send_update" name="send" type="submit" value="Update" />
<% end %>
<% form_for #profile , :html => { :multipart => true } do |f| %>
<%= render :partial => 'form', :locals => {:f => f, :profile => #profile, :title => 'Edit Profile'} %>
<%= submit_tag 'Update', :style => 'text_align:right'%>
<% end %>
Profile _form partial
<label>Upload Avatar</label>
<tr><%= f.file_field :avatar %></tr>
So basically I have two forms in the edit view and when i click on the second Update to update the avatar I go to the users update and i get this flash error "Sorry, something went wrong"
def update
#user = User.find(params[:id])
current_email = #user.email
if #user.update_attributes(params[:user])
UserMailer.deliver_email_changed (#user) if email_changed?(current_email, #user.email)
flash[:notice] = "<h1>Account updated!</h1>"
redirect_to edit_user_path(#user)
else
flash.now[:error] = "Sorry, something went wrong"
render :action => :edit
end
end
My questions are this
Is there a better way to structure this so maybe i have one form?
Why is it not saving now and whats causing the issue?
The method you are using to update is wrong, it is syntactically invalid (you're missing an end). It should be:
def update
#user = User.find(params[:id])
current_email = #user.email
if #user.update_attributes(params[:user])
UserMailer.deliver_email_changed (#user) if email_changed?(current_email, #user.email)
flash[:notice] = "<h1>Account updated!</h1>"
redirect_to edit_user_path(#user)
else
flash.now[:error] = "Sorry, something went wrong"
render :action => :edit
end
end
It should be two forms indeed, as I'm guessing you don't want any of the values of one form to submit if the user performs the other action.
Now, organize your controllers. You are calling #user = User.find(params[:id]) on your ProfilesController, but the id you're passing is an user's one. Either this should be on the user's controller, and update the associated profile from there, or you should receive the id of the profile object instead.
I'd go with the first one. You can update the Profile object of a user using accepts_nested_attributes_for, and your forms would be like:
<% form_for #user do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.password_field :password_confirmation %>
<%= f.submit, :id => ... %>
<% end %>
<% form_for #user, :html => { :multipart => true } do |f| %>
<% f.fields_for :profile do |profile_form| %>
<%= render :partial => 'form', :locals => {:f => profile_form, :title => 'Edit Profile'} %>
<%= submit_tag 'Update', :style => 'text_align:right'%>
<% end %>
<% end %
If the error is that the password cannot be blank, may be due to a validates_presence_of :password, :password_confirmation. You should use a conditional validation there
Troubleshooting would help:
Remove the if/else and keep the #user.update_attributes(params[:user]). Rails would give you a more detailed error message.
Check the form structure (html source) especially for field naming.
Check the log files for DB statements
HTH