Ruby on Rails - f.error_messages not showing up - ruby-on-rails

I've read many posts about this issue but I never got this to work.
My model looks like this:
class Announcement < ActiveRecord::Base
validates_presence_of :title, :description
end
My controller's create method(only its relevant part) looks like this:
def create
respond_to do |format|
if #announcement.save
flash[:notice] = 'Announcement was successfully created.'
format.html { redirect_to(#announcement) }
format.xml { render :xml => #announcement, :status => :created, :location => #announcement }
else
#announcement = Announcement.new
#provinces = Province.all
#types = AnnouncementType.all
#categories = Tag.find_by_sql 'select * from tags where parent_id=0 order by name asc'
#subcategories= ''
format.html { render :action => "new" } #new_announcement_path
format.xml { render :xml => #announcement.errors, :status => :unprocessable_entity }
end
end
end
My form looks like this:
<% form_for(#announcement) do |f| %>
<%= error_messages_for 'announcement' %> <!--I've also treid f.error_messages-->
...
What am I doing wrong?

You are killing your error messages by creating a new announcement in your else statement.
#announcement = Announcement.new # should be removed
When you call #announcement.save it will store the errors in #announcement.errors. By calling #announcement = Announcement.new after this you are going back to a clean slate. So no errors will ever be displayed.

Related

rails3 update param in controller

I want to update 2 column values in a Rails3 controller if a certain submit button is used on the form.
Submit button on form:
<%= simple_form_for #costproject, :html => {:class => 'form-horizontal'}, :validate => true do |f| %>
...
<%= f.submit 'Submit to Division', :class => 'btn btn-warning', :name => "submit1" %>
Update logic in Controller:
class CostprojectsController < ApplicationController
...
def update
...
params[:coststatus_id] = 2 if params[:submit1]
params[:submit_date] = Date.today if params[:submit1]
respond_to do |format|
if #costproject.update_attributes(params[:costproject])
flash[:success] = "Project Submitted" if #costproject.previous_changes.include?(:submit_date)
format.html { redirect_to nextpath }
format.json { render json: #costproject }
else
format.html { render action: "edit" }
format.json { render json: #costproject.errors, status: :unprocessable_entity }
end
end
end
If I stop execution with an alert, it looks like the params have been set. But, the values don't get saved to the db.
You need to update the model if you want it save to the DB. You're just changing params in your update action.
You need something like this:
def update
#cost_project = Costproject.find(params[:id])
#cost_project.update(coststatus_id: 2, submit_date: Date.today) if params[:submit1]
end
the .update will update and save the record in the DB
This seems to work:
params[:costproject][:coststatus_id] = 2 if params[:submit1]
params[:costproject][:submit_date] = Date.today if params[:submit1]
respond_to do |format|

undefined method `first_name'

Can anyone shed light on this for me?
undefined method `first_name' for #
Here is the show.html
<p id="notice"><%= notice %></p>
<div id="container">
<p>
<b>First name:</b>
<%= #artist.firstname %>
</p>
<p>
<b>Second name:</b>
<%= #artist.surname %>
</p>
<p>
<b>About:</b>
<%= #artist.about %>
</p>
<div id="comments">
<h2>Comments</h2>
<%= render :partial => "shared/comment", :collection => #artist.comments%>
</div
</div>
<%= render :partial => "image", :collection => #artist.images %>
<%= link_to 'Edit', edit_artist_path(#artist) %> |
<%= link_to 'Back', artists_path %>
<%= link_to 'show', images_path %>
Here is the partial
<div class="comment">
<p>
<span class="commentator"><%= comment.commentator.display_name %>
say's</span>
<%= comment.comment %>
</p>
</div
Here is the friend view
class Friends < ActiveRecord::Base
attr_accessible :firstname, :surname
has_many :comments, :as => :commentator, :class_name =>"Commentable"
def display_name
"#{self.firstname} #{self.surname}"
end
end
This is the friends controller
class FriendsController < ApplicationController
# GET /friends
# GET /friends.xml
def index
#friends = Friend.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #friends }
end
end
# GET /friends/1
# GET /friends/1.xml
def show
#friend = Friend.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/new
# GET /friends/new.xml
def new
#friend = Friend.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/1/edit
def edit
#friend = Friend.find(params[:id])
end
# POST /friends
# POST /friends.xml
def create
#friend = Friend.new(params[:friend])
respond_to do |format|
if #friend.save
format.html { redirect_to(#friend, :notice => 'Friend was successfully created.') }
format.xml { render :xml => #friend, :status => :created, :location => #friend }
else
format.html { render :action => "new" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# PUT /friends/1
# PUT /friends/1.xml
def update
#friend = Friend.find(params[:id])
respond_to do |format|
if #friend.update_attributes(params[:friend])
format.html { redirect_to(#friend, :notice => 'Friend was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /friends/1
# DELETE /friends/1.xml
def destroy
#friend = Friend.find(params[:id])
#friend.destroy
respond_to do |format|
format.html { redirect_to(friends_url) }
format.xml { head :ok }
end
end
end
I am trying to make it so a friend can leave a comment on an artists page but I keep getting the above error.
I am very new to Ruby so I apologise if I have left anything out.
Basically, rails will look at the database to figure out what fields are on a model. So make sure your migrations have been run, and that first_name exists on the db table.
Also, Friends is plural. In rails, your table is plural (friends), your model is singular (Friend), and your controller is plural (FriendsController). It is best not to go against this convention. Try renaming the model and see what happens
This error related to database that first_name don't exist in your db.Run migration carefully.
You need line 2 of the Friend class to be attr_accessible :firstname, :surname so your views have access to the those variables.

When submitting a form with a fields_for part, how can I assign the new id to the fields_for model

I have a form that handles 2 models, Vehiculo and Poliza. This is how I have them set up right now:
class Vehiculo < ActiveRecord::Base
has_one :poliza
end
class Poliza < ActiveRecord::Base
belongs_to :vehiculo
end
The create method on Vehiculo looks like this:
def create
#vehiculo = Vehiculo.new(params[:vehiculo])
#polizadeseguro = Polizadeseguro.new(params[:poliza])
respond_to do |format|
if #vehiculo.save #&& #poliza.save
format.html { redirect_to(#vehiculo, :notice => 'Vehiculo was successfully created.') }
format.xml { render :xml => #vehiculo, :status => :created, :location => #vehiculo }
else
format.html { render :action => "new" }
format.xml { render :xml => #vehiculo.errors, :status => :unprocessable_entity }
end
end
The form on /vehiculos/new has a #fields_for part with the fields from poliza. When I submit the form, it is saving all the fields, but it is not assigning the just created id from vehiculo, to vehiculo_id on the Polizas table. After reading many questions about this online, It seems that it should save it "automagically" based on the relationships on the model. Is this true? If so, why isn't it working? If not, what do I need to add to the create method so I resolve this?
Thanks!
Update:
After updating the create method with json as output as suggested here is what I get:
{
"utf8"=>"✓",
"authenticity_token"=>"tEhNC4J17h+KvNgXv1LLkVyufQwU2uAT18P7msQxiqA=",
"vehiculo"=>{
"marca_id"=>"2",
"modelo_id"=>"4",
"color"=>"Blanco",
"ano"=>"2011",
"chassis"=>"123456789",
"placa"=>"G123456",
"cliente_id"=>"1",
"entaller"=>"0",
"vip"=>"0"
},
"poliza"=>{
"compania"=>"Comp1",
"numeropoliza"=>"736458",
"vencimiento(1i)"=>"2011",
"vencimiento(2i)"=>"9",
"vencimiento(3i)"=>"21"
}
}
That's the output, so at least it is getting the fields from the form, but it is not inserting them to the polizas table.
You need to make sure that your parent model accepts nested attributes for the child model:
class Vehiculo < ActiveRecord::Base
has_one :poliza
accepts_nested_attributes_for :poliza
end
Assuming your form is set up correctly, your params will look something like this:
params = {
:vehiculo => {
:field => "value",
:another_field => "value",
:poliza => {
:poliza_field => "poliza value"
}
}
}
So all you should need in your controller is:
def create
#vehiculo = Vehiculo.new(params[:vehiculo])
respond_to do |format|
if #vehiculo.save #&& #poliza.save
format.html { redirect_to(#vehiculo, :notice => 'Vehiculo was successfully created.') }
format.xml { render :xml => #vehiculo, :status => :created, :location => #vehiculo }
else
format.html { render :action => "new" }
format.xml { render :xml => #vehiculo.errors, :status => :unprocessable_entity }
end
end
end
[Update]
Here's what you'll need to have to have this all work.
As mentioned above, you need accepts_nested_attributes_for.
Next, make sure your new action is building the child.
class VehiculosController < ApplicationController
def new
#vehiculo = Vehiculo.new
#vehiculo.build_poliza
end
def create
vehiculo = Vehiculo.new(params[:vehiculo])
if vehiculo.save
redirect_to root_path, :notice => "Success"
else
redirect_to root_path, :alert => "Failure"
end
end
end
Finally, in your view, reference the child model using fields_for :child_model, as such:
<%= form_for #vehiculo do |f| %>
<p>Whatever Field: <%= f.text_field :whatever %></p>
<%= f.fields_for :poliza do |p| %>
<p>Polizo Field: <%= p.text_field :something %></p>
<% end %>
<% end %>

current_user and Comments on Posts - Create another association or loop posts? - Ruby on Rails

I have created a blog application using Ruby on Rails and have just added an authentication piece and it is working nicely. I am now trying to go back through my application to adjust the code such that it only shows information that is associated with a certain user.
Currently, Users has_many :posts and Posts has_many :comments.
When a post is created I am successfully inserting the user_id into the post table. Additionally I am successfully only displaying the posts that belong to a certain user upon their login in the /views/posts/index.html.erb view. My problem is with the comments.
For instance on the home page, when logged in, a user will see only posts that they have written, but comments from all users on all posts. Which is not what I want and need some direction in correcting. I want only to display the comments written on all of the logged in users posts.
Do I need to create associations such that comments also belong to user? Or is there a way to adjust my code to simply loop through post to display this data.
I have put the code for the PostsController, CommentsController, and /posts/index.html.erb below and also my view code but will post more if needed.
class PostsController < ApplicationController
before_filter :authenticate
auto_complete_for :tag, :tag_name
auto_complete_for :ugtag, :ugctag_name
def index
#tag_counts = Tag.count(:group => :tag_name,
:order => 'count_all DESC', :limit => 20)
conditions, joins = {}, :votes
#ugtag_counts = Ugtag.count(:group => :ugctag_name,
:order => 'count_all DESC', :limit => 20)
conditions, joins = {}, :votes
#vote_counts = Vote.count(:group => :post_title,
:order => 'count_all DESC', :limit => 20)
conditions, joins = {}, :votes
unless(params[:tag_name] || "").empty?
conditions = ["tags.tag_name = ? ", params[:tag_name]]
joins = [:tags, :votes]
end
#posts= current_user.posts.paginate(
:select => "posts.*, count(*) as vote_total",
:joins => joins,
:conditions=> conditions,
:group => "votes.post_id, posts.id ",
:order => "created_at DESC",
:page => params[:page], :per_page => 5)
#popular_posts=Post.paginate(
:select => "posts.*, count(*) as vote_total",
:joins => joins,
:conditions=> conditions,
:group => "votes.post_id, posts.id",
:order => "vote_total DESC",
:page => params[:page], :per_page => 3)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #posts }
format.json { render :json => #posts }
format.atom
end
end
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #post }
end
end
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
def edit
#post = Post.find(params[:id])
end
def create
#post = current_user.posts.create(params[:post])
respond_to do |format|
if #post.save
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to(#post) }
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
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
flash[:notice] = 'Post was successfully updated.'
format.html { redirect_to(#post) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to(posts_url) }
format.xml { head :ok }
end
end
end
CommentsController
class CommentsController < ApplicationController
before_filter :authenticate, :except => [:show, :create]
def index
#comments = Comment.find(:all, :include => :post, :order => "created_at DESC").paginate :page => params[:page], :per_page => 5
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #comments }
format.json { render :json => #comments }
format.atom
end
end
def show
#comment = Comment.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #comment }
end
end
# GET /posts/new
# GET /posts/new.xml
# GET /posts/1/edit
def edit
#comment = Comment.find(params[:id])
end
def update
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.update_attributes(params[:comment])
flash[:notice] = 'Comment was successfully updated.'
format.html { redirect_to(#comment) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
respond_to do |format|
if #comment.save
flash[:notice] = "Thanks for adding this comment"
format.html { redirect_to #post }
format.js
else
flash[:notice] = "Make sure you include your name and a valid email address"
format.html { redirect_to #post }
end
end
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to Post.find(params[:post_id]) }
format.js
end
end
end
View Code for Comments
<% Comment.find(:all, :order => 'created_at DESC', :limit => 3).each do |comment| -%>
<div id="side-bar-comments">
<p>
<div class="small"><%=h comment.name %> commented on:</div>
<div class="dark-grey"><%= link_to h(comment.post.title), comment.post %><br/></div>
<i><%=h truncate(comment.body, :length => 100) %></i><br/>
<div class="small"><i> <%= time_ago_in_words(comment.created_at) %> ago</i></div>
</p>
</div>
<% end -%>
I believe you can set up another relation on user model
has_many :comments, :through => :posts
and then user #user.comments.
First, don't mess with MVC. Line:
Comment.find(:all, :order => 'created_at DESC', :limit => 3)
should be in controller:
#comments = Comment.find(:all, :order => 'created_at DESC', :limit => 3)
and in view:
<% #comments.each do |comment| %>
Or even better with partials:
<%= render :partial => "comment_item", :collection => #comments %>
It will iterate over all #comments.
Next, if you want to display all comments assigned to a post, then relation post has_many comments is enough. Use it like this:
# controller
#posts = current_user.posts(:include => :comments)
# view
<% #posts.each do |post| %>
<%=h post.title %> - Comments: <br />
<% post.comments.each do |comment| %>
<%=h comment.body %>
<% end %>
<% end %>
If you want to show only comments posted by current_user then all your comments should have user_id field filled. And use it in the same way as you are showing users posts.

Return original selection in collection_select when editing entry

I'm trying to get my head around collection_selects in Rails. I can populate the dropdown from a database table, submit the selected option, and show the result. However I can't figure out how to show the selected option in the dropdown when the user chooses to edit the entry.
Here's an extract from my view code:
<p>
<%= f.label :Status %><br />
<%= f.text_field :status %>
</p>
<p>
<%= f.label :Manager %><br />
<%= f.collection_select(:manager, #managers, :id, :name, {:include_blank => true}) %>
</p>
Here's my controller code:
class ProjectsController < ApplicationController
# GET /projects
# GET /projects.xml
before_filter :require_user
def index
#projects = Project.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #projects }
end
end
# GET /projects/1
# GET /projects/1.xml
def show
#project = Project.find(params[:id])
projectid = params[:id]
#evidence = Evidence.find(:all, :conditions => ["projectid = ?", projectid])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #project }
end
end
# GET /projects/new
# GET /projects/new.xml
def new
#project = Project.new
#managers = Manager.find(:all)
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #project }
end
end
# GET /projects/1/edit
def edit
#project = Project.find(params[:id])
#managers = Manager.find(:all)
end
# POST /projects
# POST /projects.xml
def create
#project = Project.new(params[:project])
respond_to do |format|
if #project.save
flash[:notice] = 'Project was successfully created.'
format.html { redirect_to(#project) }
format.xml { render :xml => #project, :status => :created, :location => #project }
else
format.html { render :action => "new" }
format.xml { render :xml => #project.errors, :status => :unprocessable_entity }
end
end
end
# PUT /projects/1
# PUT /projects/1.xml
def update
#project = Project.find(params[:id])
respond_to do |format|
if #project.update_attributes(params[:project])
flash[:notice] = 'Project was successfully updated.'
format.html { redirect_to(#project) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #project.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.xml
def destroy
#project = Project.find(params[:id])
#project.destroy
respond_to do |format|
format.html { redirect_to(projects_url) }
format.xml { head :ok }
end
end
end
And here's the code for my models:
class Manager < ActiveRecord::Base
has_many :projects
end
class Project < ActiveRecord::Base
belongs_to :manager
validates_presence_of(:name, :reference, :client, :status)
validates_uniqueness_of (:reference)
end
Any help is greatly appreciated.
Thanks!
According to the documentation:
collection_select(object, method, collection, value_method, text_method,
options = {}, html_options = {})
...The value returned from calling method
on the instance object will be
selected.
This means that your :manager method must return a value that matches one of the managers in your #managers instance variable in order for that to be the selected option.
I think you need to change :manager to :manager_id:
<%= f.collection_select(:manager_id, #managers, :id, :name, {:include_blank => true}) %>

Resources