I have two models: Schedule and Project. Schedule belongs_To Project and Project has_one schedule. There are several problems, but i think they all have the same cause. Here is the code for the schedules#create controller:
def create
#schedule = Schedule.new(schedule_params)
#schedule.project = Project.find(params[:project_id])
if #schedule.project.student_id == current_user.id
if #schedule.save && #schedule.freelancer_accepts
flash[:notice] = "Successfully created schedule."
redirect_to profile_path(current_user.profile_name)
else
render :action => 'new', :notice => 'Invalid Schedule'
end
else
render :action => 'new', :notice => 'Schedule is invalid.'
end
end
Here are the problems:
Even though it is a has_one relationship, I am still able to create many schedules for a single project. This led me to change my controller to this:
def create
if !Schedule.where(project_id: params[:project_id]).any?
#schedule = Schedule.new(schedule_params)
#schedule.project = Project.find(params[:project_id])
if #schedule.project.student_id == current_user.id
if #schedule.save && #schedule.freelancer_accepts
flash[:notice] = "Successfully created schedule."
redirect_to profile_path(current_user.profile_name)
else
render :action => 'new', :notice => 'Invalid Schedule'
end
else
render :action => 'new', :notice => 'Schedule is invalid.'
end
else
render :action => 'new', :notice => 'A schedule has already been created.'
end
end
The change was that I essentially wrapped the controller in an if that says "if a schedule exists, don't create one. After I changed my code, I got the following problems:
In firefox, when I press the submit button to create a new schedule, i get this error:
First argument in form cannot contain nil or be empty
In Safari, when I press the submit button to create a new schedule, the page turns white. Furthermore, every time I try to go back to the page which displays the form, the page goes white. It is very strange.
How do I fix this? Thanks.
UPDATE: My routes and form view might help:
routes:
resources :projects do
resources :schedules
end
First part of form:
<%= form_for [#project, #schedule] do |f| %>
Turns out this and several other problems i was having was not actually caused by the has_one relationship. There was some type of problem with my cache. I'm not exactly sure what it was, but by disabling the cache I was able to fix the problem.
Related
def create
#purchase = Purchase.new(params[:purchase])
if session[:purchase_id] != #purchase.save
redirect_to(#purchase, :notice => "Thank you. You good lookin person you.")
end
end
I'm trying to either
A - Redirect to a URL, or other controllers path, or
B - refresh the form they ordered from (the new_purchases_path) and flash :notice the user that their purchase was successful. When I try to add a Url (that would be a thank you message page) i get syntax errors. This code redirects the user to the index list (which is inaccesible to them)
If I take out the def create, it by default flashes a notice and shows them their completed form. I'm using simple_form and I'm not sure how to override those defaults. Any suggestions on at least redirecting to a url?
Examples:
A - Redirect to a URL, or other controllers path
redirect_to :action => "show", :id => 5
redirect_to "http://www.rubyonrails.org"
redirect_to new_purchases_path
redirect_to purchases_url
redirect_to :back
B - refresh the form they ordered from (the new_purchases_path)
render :action => "new"
Edit:
Here a general example with flash messages:
if #foo.save
redirect_to foos_path, :notice => "Foo saved"
else
flash[:notice] = "Some errors occured"
render :action => "new"
end
here is an example of a create method i made today
def create
#book = Book.new(params[:book])
if #book.save
redirect_to searchbook_path, notice: 'Book was successfully saved'
else
render :action => 'results'
end
end
So in your case you could maybe try this
def create
#purchase = Purchase.new(params[:purchase])
if #purchase.save
redirect_to purchase_path, :notice 'Thanks for your purchase'
else
render :action => 'new'
end
end
This is assuming that you have a purchase and new path... Though it would help if you could let us know what errors you are getting
I'm using Rails 3 for this one. I've got a collections model, a user model and an intermediate subscription model. This way a user can subscribe to multiple collections, with a particular role. However, I don't want a user to be able to subscribe to the same collection twice.
So in my Subscription model I've got something like:
validate :subscription_duplicates
def subscription_duplicates
self.errors.add_to_base "This user is already subscribed" if Subscription.where(:user_id => self.user.id, :collection_id => self.collection.id)
end
However this seems ugly. Also, it breaks when I want to do something like the following in my collection controller:
def create
#collection = Collection.new(params[:collection])
#collection.subscriptions.build(:user => current_user, :role => Subscription::ROLES['owner'])
#collection.save
respond_with(#collection)
end
When I do the build the subscription does not have an id so I get a "Called id for nil" error.
Thanks for any guidance!
use validates_uniqueness_of
validates_uniqueness_of :user_id, :scope => :collection_id
First of all, your create action should always test if the object was saved, and if not then handle that (usually by re-rendering the new/edit page and showing the errors to the user).
A standard sort of create action would look like this (for a #post in this case):
def create
#post = Post.new(params[:post])
#created = #post.save
respond_to do |format|
if #created
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to #post }
format.xml { render :xml => #post, :status => :created, :location => #post }
format.js
else
format.html { render :action => :new } #or edit or wherever you got here from
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
format.js
end
end
end
Shingara's approach to avoiding duplicates should work fine for you.
I'm using Ruby on Rails 2.3.8 and I've got a registration form in which I receive a parameter as follows: /registration/4, which 4 is the id of a user who recommended the user that is about to register in the website.
The problem is that if the validation fails when the user submits the registation (the form renders to the controller users, action create_particular) the site will redirect to /users/create_particular, and therefore I lose the parameter with value 4 that I had before. Besides, I want the user to stay at the same url, which is /registration/4
How can I do that?
Then you should rewrite your create method. You should use redirect_to :back instead of render :action
UPD
def new
#word = Word.new(params[:word])
#word.valid? if params[:word]
end
def create
#word = Word.new(params[:word])
if #word.save
redirect_to #word
else
redirect_to new_word_path(:word => params[:word] )
end
end
Looks quite dirty, but this is just a scratch
UPD 2
This is really not the best solution, but it works
# routes.rb
match 'words/new' => 'words#create', :via => :post, :as => :create_word
# words_controller
def new
#word = Word.new
end
def create
#word = Word.new(params[:word])
respond_to do |format|
if #word.save
format.html { redirect_to(#word, :notice => 'Word was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
# views/words/new.html.erb
<%= form_for(#word, :url => create_word_path) do |f| %>
...
<% end %>
Submit to the current URI (e.g. action=""). When the submission is valid, redirect. POST->Redirect->GET is a good habit.
From the top of my head:
Edit your controller (registrations_controller.rb file). Create method by default contains following piece of code:
if #registration.save
format.html { }
format.xml { }
else
format.html { }
format.xml { }
end
Add redirect_to (:back) between brackets to else format.html{}
Ok I solved the problem by doing the following:
1) I created two routes with the same path, but with different conditions method (one it's post and the other one is set to get)
2) I changed the form in order to post to the POST action defined above
3) I added render => :my_action when the validation fails
So that's pretty much it.
Thanks anyway for all your help.
Hidden field. That user ID param has a name by which you extract it in your controller, right? So just put that value in a hidden field of the same name, then it will survive a round-trip.
For example:
<%= hidden_field_tag :referring_user_id, params[:referring_user_id] %>
I'm allowing users to create a 'Question' from different pages in the app, and want them to be redirected to the right page after the new question is saved. Since one page has a params[:id] and one doesn't, I thought I'd use that to differentiate between the different redirects.
Here's what I was trying to do in my Questions controller:
respond_to do |format|
if #question.save
if params[:id].nil?
format.html {redirect_to :controller => 'home', :action => 'show', :username => question.directed_to}
else
format.html {redirect_to :controller => 'mentions', :action => 'show', :id => question.topic}
end
else
...
end
Thanks very much, I'm still new to this.
Relying on params beings nil is super awkward. You have control of the forms being submitted, so just sent an extra parameter yourself which identifies where it's coming from.
A few other things:
If you're only responding with html, don't bother doing the respond_to block.
if #question.save
redirect_to :controller => 'home', :action => 'show', :username => question.directed_to
else
redirect_to :controller => 'mentions', :action => 'show', :id => question.topic
end
#question.save doesn't run validations. It's pretty unusual that you'd want to have a create action that doesn't run validations. You should probably having something like:
def create
#question = Question.new(params[:question])
#question.save!
flash[:notice] = "Question saved successfully"
# Do your redirects here
rescue ActiveRecord::RecordInvalid
flash[:error] = "There were errors saving your question"
render :action => :new
end
I'm trying to redirect from one controller to another in Rails and I am getting this error:
undefined method `call' for nil:NilClass
The code is pretty simple (in def create method):
#blog_post_comment = BlogPostComment.new(params[:blog_post_comment])
respond_to do |format|
if #blog_post_comment.save
flash[:notice] = 'Comment was successfully created.'
redirect_to(#blog_post_comment.blog_post)
else
render :action => "new"
end
end
Save goes ok, the value gets into the database. How can I work around the redirect fail?
Form:
<% form_for #blog_post_comment do |f| %>
<%= f.hidden_field :blog_post_id %>
...
UPD:
After some investigation, it turned out that problem was in the line respond_to do |format| in the blog_post_comment controller. Once I removed it, everything is OK now.
Assuming you have an association, you can find your comment like this:
#blog_post = BlogPost.find(params[:blog_post_id])
#blog_post_comment = #blog_post.comments.build(params[:blog_post_comment])
And then
respond_to do |format|
if #blog_post_comment.save
flash[:notice] = 'Comment was successfully created.'
redirect_to(#blog_post)
else
render :action => "new"
end
end
If you don't have an association, here's how you set it up:
In your BlogPost model, you should have the following line:
has_many :blog_post_comments
And in your BlogPostComment model, you should have:
belongs_to :blog_post
In routes.rb, you should have:
map.resources :blog_post_comment, :has_many => 'blog_post_comments'