Rails 3 form_for ajax call - ruby-on-rails

I have method in my controller:
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
redirect_to company_path
end
On my view:
<%= render 'companies/work_form' if signed_in? %>
_work_form.html.erb:
<%= form_for company, :remote => true, :url => { :controller => "companies", :action => "work_here" } do |f| %>
<%= f.hidden_field :id, :value => company.id %>
<%= f.submit "I working here" %>
<% end %>
And I have a work_here.js.erb file:
$("#work_at_form").html("<%= escape_javascript("render('companies/works')") %>")
But my form works without ajax request(in other pages ajax forks fine), my js.erb file never use.
Can anyone give me advise?
Thanks.

The work_here.js.erb can't be read because you never call it. A redirect is allways do. render it when the request is js format.
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
respond_to do |format|
format.html { redirect_to company_path }
format.js { render }
end
end

Related

Ruby on Rails Form Submission Error and Success Messages

I'm creating a landing page and I have two forms on my root page (trying to create a landing page). Very new to ruby on rails so forgive me because I'm going to explain this terribly.
The landing page controller (landing_controller) looks like this:
class LandingController < ApplicationController
def index
#email = Email.new
#design = Design.new
end
end
The emails_controller (emails_controller) looks like this:
class EmailsController < ApplicationController
protect_from_forgery with: :exception
def new
#email = Email.new
end
def create
#email = Email.new(params[email_params])
respond_to do |format|
if #email.save
format.html { redirect_to(root_path, :notice => 'Thank You For Subscribing!') }
format.json { render json: Email.create(email_params) }
else
format.html { redirect_to(root_path)}
format.json { render :json => #email.errors, :status => :unprocessable_entity }
end
end
end
private
def email_params
params.require(:email).permit(:username, :email)
end
end
and the designs controller (designs_controller) looks pretty much the same as emails_controller.
Then I have some validation in the email.rb model:
class Email < ActiveRecord::Base
validates :username, :presence => true
validates :email, :presence => true
end
And again the design.rb looks pretty much the same.
The form I have on the landing page (root_path) index looks like this:
<%= form_for #email, url: emails_path, html: {class: "email-form"} do |f| %>
<% if #email.errors.any? %>
<h3>Error</h3>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<h2>Receive Notifications</h2>
<%= f.text_field :username, :class => 'email-box', :placeholder => "First Name", :autocomplete => :off %>
<%= f.text_field :email , :class => 'email-box', :placeholder => "Email", :autocomplete => :off %>
<%= f.submit "Subscribe", :class => 'email-submit' %>
<p class="info">- We'll update ​you ​when ​we launch our new website</p>
<% end %>
When I submit the form breaking the validation I get no errors and if I submit the form following the validation rules I don't know if it creates a new entry in the database. If anyone can help I'd be very appreciative.
you need to render the landing controller index action rather than redirecting to it. because on redirection, it does #email = Email.new and all the errors are gone for email. try this as create action in your emails controller
def create
#email = Email.new(email_params)
respond_to do |format|
if #email.save
format.html { redirect_to root_path, notice: 'Thank You For Subscribing!' }
format.json { render json: Email.create(email_params) }
else
#design = Design.new
format.html { render "landing/index" }
format.json { render :json => #email.errors, :status => :unprocessable_entity }
end
end
end
for success or errors messages, put this in your application.html.erb
<% if flash[:error].present? %>
<p class='flash-error'><%= flash[:error] %></p>
<% end %>
<% if flash[:notice].present? %>
<p class='flash-notice'><%= flash[:notice] %></p>
<% end %>

Update Button Via AJAX

I have a button that adds a vote to a post whenever a user clicks it. The posts are being rendered in the index view, but when the button is clicked for a user to add a vote, I get a 500 error in the console, but on refresh the vote has been added. Below is the code I'm using:
Pages Controller where the posts are being rendered:
#posts = current_user.feed.paginate(:per_page => 6, page: params[:page])
Favorites Controller:
def create
current_user.favorites.create(:post_id => params[:post_id])
respond_to do |format|
format.html { redirect_to post }
format.js { render :toggle }
end
end
Toggle.js.erb (favorites/toggle.js.erb)
$("#favorite").html("<%= escape_javascript render('shared/fave_form') %>");
Favorite Form
<% if current_user.favorites.find_by_post_id(post.id) %>
<% else %>
<%= form_for favorite, :html => { :method => :delete }, :remote => true do |f| %>
<%= f.submit "Unlike" %>
<% end %>
<% end %>

Update database using 'update_attributes' through 'has_many'

I'm having a problem getting my first app (I'm a total newbie) to save a new associated record. I have two models (users and pictures) with a has_many/belongs_to association. I have set up the userController so that it can create a new picture as below:
def new_picture
#user = User.find(current_user.id)
#picture = #user.pictures.build
end
def create_picture
#user = User.find(params[:id])
#picture = #user.pictures.build(params[:picture])
if #picture.save
flash[:notice] = "Your picture was successfully added."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
and I use
<%= link_to("add picture", :action => 'new_picture', :id => #user.id) if current_user %>
to add a new one. But I'd also like to be able to edit. So I updated the usercontroller with some new code:
def edit_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:id])
end
# When the user clicks the save button update record
def update_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:picture])
respond_to do |format|
if #picture.update_attributes(params[:picture])
flash[:notice] = "Your picture was successfully updated."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
end
and added the edit link to show.erb:
<%= link_to("edit picture", :action => 'edit_picture', :id => picture.id) if current_user %>
It loads the edit form fine, with the data all in the right place, but on save all it's doing is giving me the error 'ArgumentError in UsersController#update_picture' with a bunch of Unknown key(s) from my pictures table.
Could somebody explain why? I feel like there is one piece of the jigsaw I haven't quite understood here....
Thanks in advance!
UPDATE: View code is as follows:
<h1>New picture for <%= #user.name %></h1>
<% form_for :picture, #picture, :html => { :multipart => true }, :url => {:action => 'update_picture', :id => #user.id} do |f| %>
Can't seem to see your problem in the view code, however you can do the same thing more elegantly (RESTful) as a nested route. That way you might be able to see the problem more clearly.
config/routes.rb:
resources :users do
member do
resources :pictures
end
end
app/controllers/pictures_controller.rb:
class PicturesController < ApplicationController
before_filter :find_picture, :only => [:edit, :update]
def edit
end
def update
if #picture.update_attributes params[:picture]
flash[:notice] = "Your picture was successfully updated."
redirect_to user_path(current_user)
else
render :edit
end
end
protected
def find_picture
#picture = current_user.pictures.find params[:id]
end
end
app/views/pictures/edit.html.erb:
<%= form_for [current_user, #picture] do |f| %>
<!-- some stuff -->
<% end %>
and to link to your edit form:
<%= link_to_if current_user, 'edit picture',
edit_user_picture_path(:user => current_user, :id => picture) %>
I suggest adding 'accepts_nested_attributes_for :pictures to the user model, and then do
<%= form_for #user do |form| %>
.. user fields
<%= form.fields_for :pictures do |picture_form| %>
.. picture fields
<% end %>
<%= form.submit %>
<% end %>
in the view.
Another option is to create a new controller for the pictures. That may be simpler.

Why can't I build more than one nested attribute here?

this is my form code:
<%= simple_form_for setup_video(#video) do |f| %>
<% f.fields_for :comment_titles do |t| %>
<%= t.input :title, :label => "Comment Title:" %>
<%= t.button :submit, :value => 'Add', :id => 'add_comment_title' %>
<div class='hint'>Let your listeners know what comments you want by adding a guiding title for them. Pose a question, ask for feedback, or anything else!</div>
<% end %>
<% end %>
I have has_many :comment_titles and accepts_nested_attributes_for :comment_titles, :comments in my model. when I create a new comment_title in the form, the old one is replaced. I want an additional one to be built. How can I do this?
Here are the video controller actions:
def new
#video = Video.new
respond_to do |format|
format.js do
render_to_facebox(:partial => 'add_video')
end
end
end
def create
#video = current_user.videos.new(params[:video])
respond_to do |format|
if #video.save
format.html { redirect_to(#video) }
else
format.html { render :action => "new" }
end
end
end
I think this is actually what is needed:
def update
#video = current_user.videos.find(params[:id])
respond_to do |format|
if #video.update_attributes(params[:video])
format.html { redirect_to(#video) }
format.js
else
format.html { render :action => "edit" }
end
end
end
The edit action here will provide a form which will allow you to edit the existing record as well as its nested attributes. This is why it's replacing the existing object.
If you only want people to add new comment titles then I would recommend building a new object in your edit action like this:
def edit
video = current_user.videos.find(params[:id])
video.comment_titles.build
end
Then this will be available as an additional row in your fields_for call. To only make this show new objects:
<% f.fields_for :comment_titles do |t| %>
<% if t.object.new_record? %>
# stuff goes here
<% end %>
<% end %>
However this restricts people to being able to only add new items in an edit action, which may seen counter-intuitive to some users.

Rails: Problem with routes and special Action

Sorry for this question but I can't find my error!
In my Project I have my model called "team".
A User can create a "team" or a "contest". The difference between this both is, that contest requires more data than a normal team.
So I created the columns in my team table.
Well... I also created a new view called create_contest.html.erb :
<h1>New team content</h1>
<% form_for #team, :url => { :action => 'create_content' } do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p>
<%= f.label :url %><br />
<%= f.text_fiels :url %>
</p>
<p>
<%= f.label :contact_name %><br />
<%= f.text_fiels :contact_name %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
In my teams_controller, I created following functions:
def new_contest
end
def create_contest
if #can_create
#team = Team.new(params[:team])
#team.user_id = current_user.id
respond_to do |format|
if #team.save
format.html { redirect_to(#team, :notice => 'Contest was successfully created.') }
format.xml { render :xml => #team, :status => :created, :location => #team }
else
format.html { render :action => "new" }
format.xml { render :xml => #team.errors, :status => :unprocessable_entity }
end
end
else
redirect_back_or_default('/')
end
end
Now, I want on my teams/new.html.erb a link to "new_contest.html.erb".
So I did:
<%= link_to 'click here for new contest!', new_contest_team_path %>
When I go to the /teams/new.html.erb page, I get following error:
undefined local variable or method `new_contest_team_path' for #<ActionView::Base:0x16fc4f7>
So I changed in my routes.rb, map.resources :teams to map.resources :teams, :member=>{:new_contest => :get}
Now I get following error: new_contest_team_url failed to generate from {:controller=>"teams", :action=>"new_contest"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["teams", :id, "new_contest"] - are they all satisfied?
I don't think adding :member => {...} is the right way doing this. So, can you tell me what to do? I want to have an URL like /teams/new-contest or something.
My next question: what to do (after fixing the first problem), to validate presentence of all fields for new_contest.html.erb? In my normal new.html.erb, a user does not need all the data. But in new_contest.html.erb he does. Is there a way to make a validates_presence_of only for one action (in this case new_contest)?
UPDATE:
Now, I removed my :member part from my routes.rb and wrote:
map.new_contest '/teams/contest/new', :controller => 'teams', :action => 'new_contest'
Now, clicking on my link, it redirects me to /teams/contest/new - like I wanted - but I get another error called:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
I think this error is cause of #team at <% form_for #team, :url => { :action => 'create_content_team' } do |f| %>
What to do for solving this error?
I'm not sure about how your models work, but in my code I've always written;
#team.user_id = #current_user.id
instead of
#team.user_id = current_user.id
That would mean the id wasn't being passed to the controller giving you the error, wouldn't it?
Okay, I found my errors.
For the record:
First of all, I forgot to write the code inside my def new_contest. Here it is:
def new_contest
if #can_create
#team = Team.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #team }
end
else
redirect_back_or_default('/')
end
end
There were several typos, too, in my .erb file like text_fiels instead of text_field or create_content instead of create_contest.
current_user is working fine for me.

Resources