Rails - Controller :notice - Add a variable? - ruby-on-rails

I'm green behind the ears, but had a basic question about modifying the scaffolding's :notice to add a variable. For example, rails created the following create method for me:
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
format.html { redirect_to(#order, :notice => 'Order was successfully created.') }
format.xml { render :xml => #order, :status => :created, :location => #order }
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
end
What I'm looking to do is add a variable to :notice so that it would print specifically what order was created (or edited with the update method). I tried some basic things using such as passing <%= order.id %>,though I felt this seemed unnatural within the controller?
Is adding a dynamic value possible within this format of this scaffolding? Or is it against the convention.
I appreciate the help, sorry if this is very newbish.

Beestings are the preferred way to insert dynamic values into strings in ruby. So if you wanted #order.id in your :notice, you could do this:
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
format.html { redirect_to(#order, :notice => "Order id # #{#order.id} was successfully created.") }
format.xml { render :xml => #order, :status => :created, :location => #order }
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
end

Related

Add default table field when creating new obect Ruby on Rails 3

My models are: Projects has_many Feeds. I just added a column to my Feeds table called feed_error. I currently have a form on the app that creates a new Feed when entered. I want to be able to set feed_error to false by default. In my feeds_controller, I have my create method:
def create
#feed = Project.find(params[:project_id]).feeds.build(params[:feed])
respond_to do |format|
if #feed.save
format.html { redirect_to( :back, :notice => 'Feed was successfully created.') }
format.xml { render :xml => #feed, :status => :created, :location => [#feed.project, #feed] }
else
format.html { render :action => "new" }
format.xml { render :xml => #feed.errors, :status => :unprocessable_entity }
end
end
end
I was thinking I could try adding :feed_error => 'false' to the params, but that doesn't seem to work. How do I set this field by default?
You have a couple options. In your controller you can do:
def create
#feed = Project.find(params[:project_id]).feeds.build(params[:feed])
#feed.feed_error = false
respond_to do |format|
if #feed.save
format.html { redirect_to( :back, :notice => 'Feed was successfully created.') }
format.xml { render :xml => #feed, :status => :created, :location => [#feed.project, #feed] }
else
format.html { render :action => "new" }
format.xml { render :xml => #feed.errors, :status => :unprocessable_entity }
end
end
end
You could also set this up in your database migration. For example, if you don't need a null value and instead want the default to be false you can add:
t.boolean "feed_error", :null => false
to your migration.

Rails3 Conditional Statements in Controller Actions

I'm trying to write a conditional statement in my tasks controllers for a simple rails3 application.
Users have many tasks and tasks have one user.
When creating a task, we can chose who owns it:
<%= collection_select(:task, :user_id, User.all, :id, :name, {:prompt => true}) %>
I want the system to send an email to the owner of the task, only when it's created for someone else. I.e. I do not need to receive an email when I create a task for myself.
My mailer's working fine and in my tasks controller, I've tried this:
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save and #task.user_id = current_user.id
format.html { redirect_to(tasks_path, :notice => 'Task was successfully created.') }
format.xml { render :xml => #task, :status => :created, :location => #task }
elsif #task.save
format.html { redirect_to(tasks_path, :notice => 'Task was successfully created.') }
format.xml { render :xml => #task, :status => :created, :location => #task }
TaskMailer.new_task(#task).deliver
else
format.html { render :action => "new" }
format.xml { render :xml => #task.errors, :status => :unprocessable_entity }
end
end
end
But it's not really working... Any chance of some assistance.
Replace #task.user_id = current_user.id with #task.user_id == current_user.id.
This is not the cause of your error, but you're saving your task two times if #task.user_id != current_user.id. You could do something like this instead:
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to(tasks_path, :notice => 'Task was successfully created.') }
format.xml { render :xml => #task, :status => :created, :location => #task }
TaskMailer.new_task(#task).deliver if #task.user_id != current_user.id
else
format.html { render :action => "new" }
format.xml { render :xml => #task.errors, :status => :unprocessable_entity }
end
end
end
end
Are you not storing the id of the creator? If you do, all the data you need is in the model. Thus just implement an private instance method in Task model. Something like the following
# Task model
private
def notify_assignee
if new_record? || user_id_changed? && creator_id != user_id
TaskMailer.new_task(#task).deliver
end
end
Call the above method after_save
# Task model
after_save :notify_assignee
In case you are not storing the creator_id in the database, create an attribute accesor called :creator_id.
# Task model
attr_accessor :creator_id
In the controller, before saving, do
# Tasks controller
#task.creator_id = current_user.id
and the above method would still work.
You controller re directions would automatically be simplified to
if #task.save
format.html { redirect_to(tasks_path, :notice => 'Task was successfully created.') }
format.xml { render :xml => #task, :status => :created, :location => #task }
else
format.html { render :action => "new" }
format.xml { render :xml => #task.errors, :status => :unprocessable_entity }
end
And also this would be the right way to go as the "business logic" (which in your case is send assignee an email notifying that someone else has assigned a task to them) would reside in the model.
It's because of this line, you're using an assignment = instead of the comparision ==
Also the current_user should be #current_user instead because you didn't specify it in the method. (Or you have a method current_user() that you did not post. Then it's fine)
if #task.save and #task.user_id = current_user.id
It should be
if #task.save and #task.user_id == #current_user.id
also imho you should move the mailing-stuff to the Task-model and use an after_save-callback.
Maybe you need change this line: #task.user_id = current_user.id to #task.user_id == current_user.id

The action could not be found for controller

Having gone through my code I have a separate problem from my original question and rather than writing a new question. I will leave the old part at the bottom of this and post the new problem here. I do this because they are closely related.
New:
Im getting an error message saying
Unknown action
The action 'response' could not be found for CrawlerController
I'll keep it simple but the code for model, controller and routes are below in the previous question.
A basic run down is response is a def within CrawlerController as is add_Request.
The routes are matched as such:
match "/requests/new" => "crawler#add_Request"
match 'requests/:id' => 'crawler#response'
Here is controller code as per user request:
class CrawlerController < ApplicationController
def add_Request
#request = Request.new(params[:request])
respond_to do |format|
if #request.save
format.html { redirect_to(#request, :notice => 'Request was successfully created.') }
format.xml { render :xml => #request, :status => :created, :location => #request }
else
format.html { render :action => "new" }
format.xml { render :xml => #request.errors, :status => :unprocessable_entity }
end
end
end
def response
#request = Request.find(params[:id])
respond_to do |format|
format.html
format.js { render :json => #request }
end
end
def show
#request = Request.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #request }
format.json{
render :json => #request.to_json
}
end
end
end
please recheck code of controller as I can see it
class CrawlerController < ApplicationController
def add_Request
#request = Request.new(params[:request])
respond_to do |format|
if #request.save
format.html { redirect_to(#request, :notice => 'Request was successfully created.') }
format.xml { render :xml => #request, :status => :created, :location => #request }
else
format.html { render :action => "new" }
format.xml { render :xml => #request.errors, :status => :unprocessable_entity }
end
end
def response
#request = Request.find(params[:id])
respond_to do |format|
format.json {render :#request.to_json}
end
end
so one end is missing an your response action is defined inside add_Request

Missing templates from new Rails 3 app?

Just tried writing a simple validates_presence_of in my model, and when the errors try to render, it calls this :
Template is missing
Missing template posts/create with {:locale=>[:en, :en], :handlers=>[:builder, :rjs, :erb, :rhtml, :rxml, :haml], :formats=>[:html]} in view paths "/Users/johnsmith/Sites/shwagr/app/views"
Errors don't have seperate views in Rails3 do they? I thought that was Rails magic..
Curious if anyone had this problem, or knew how to make it correctly validate.
My Model:
validates_presence_of :category, :name, :url
My Controller:
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
def create
#post = Post.new(params[:post])
if #post.valid? && current_user.posts << #post
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
end
Update
Interesting, I 'touch app/views/posts/create.html.haml', and now it removed the error and instead loads that page instead. But why would it? Or more importantly, how can I make it just redirect back to the new_post_path(#post) like it should?
If your
if #post.valid? && current_user.posts << #post
line returns false, no render() or redirect_to() is called. Rails' default behavior then is to render the view with the same name as your method. That would be create.BUILDER.FORMAT.
Try to remove the line. Use this code instead:
#post = current_user.posts.new(params[:post])
respond_to do |format|
if #post.save
...
Or write an else case with
render :action => "new"
Ah got it. This is because it was never valid so it would loop back to itself on 'create', find no template there and error out. The correct way to set up the def create would be this
def create
#post = Post.new(params[:post])
if #post.valid? && current_user.posts << #post
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
format.xml { render :xml => #post, :status => :created, :location => #post }
else
format.html { redirect_to new_user_post_path(:current) }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
else
render :action => 'new'
end
end
No, they don't have seperate views. So do you have a app/views/posts/create.html.erb file?

Rails, Is there any way in my view use link_to to grab the contents of a specific field and place it in a ruby variable?

Basically I am trying to capture the value of the form field before it is saved to the database. Then I intend to use that value in my controller to update a specific field in the database,
using
#taskforms.update_attribute('notes',
$notes)
I need to do this because I know of no other way to update that that does not require the full record to be validated.
The suggestion below to use #taskforms.save(false) is really not what I was looking for optimally. However it could work. However having and issue to get it to work.
What I am currently using (that works with validations)
def myupdate
#taskforms = Taskforms.find(params[:id])
respond_to do |format|
if #taskforms.update_attributes(params[:taskforms])
#taskforms.update_attribute('edited_at', Time.new )
flash[:notice] = 'Note was successfully updated.'
format.html { redirect_to(:controller => "taskforms", :action => "displayedit", :id => #taskforms.id) }
format.xml { head :ok }
else
format.html { render :action => "displayedit" }
format.xml { render :xml => #taskforms.errors, :status => :unprocessable_entity }
end
end
end
However when I try the save(false) it doesn't save and triggers validations anyway
def myupdate
#taskforms = Taskforms.find(params[:id])
if #taskforms.save(false)
#taskforms.update_attribute('edited_at', Time.new )
flash[:notice] = 'Note was successfully updated.'
format.html { redirect_to(:controller => "taskforms", :action => "displayedit", :id => #taskforms.id) }
format.xml { head :ok }
else
format.html { render :action => "displayedit" }
format.xml { render :xml => #taskforms.errors, :status => :unprocessable_entity }
end
end
I have never used Save in the past just the default respond_to do |format| so suspect my code is incorrect.
#taskforms.save(false) will save your model without any validations if that is your main goal.

Resources