In respond_to you can set flash[:notice] like this
respond_to do |format|
format.html { redirect_to photo_path(photo), :notice => 'The photos was saved') }
format.xml { render :xml => photo, :status => :created}
end
I am trying to set flash[:success] with :success => "yay" but it doesn't work.
Am I doing something wrong?
You should use redirect_to differently :
redirect_to photo_path(photo), :flash => { :success => "Yeepee!" }
The only flashes you can use directly are
:notice
:alert
:error
Hope that helps
From Rails 4, you can directly use :success in redirect_to.
Just add this line:
# in app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
[...]
add_flash_types :error, :success, :info
[...]
Without this line, in respond_to, :notice produces flash, but :success doesn't work.
Hat tip to Milan Mondal's post for this!
Related
I have a Page Model that has a :name attribute. I have a specific route for the Page Model with the name "home", because I want this specific Page record to be found at the root_url. This works.. but because I'm hard coding the route... I only want users with the role "super_admin" to be able to change the :name attribute, on the Page model, where the name == "home". For example, users with the "admin" role should not be able to change the :name attribute on the "home" Page.
Can I get that fine grained with CanCan?
Should I put this logic in the PageControllers update action?
Should I set the "page#show" route differently (not hard code it)?
Not sure how to do any of these.
Thanks in advance for any advice!
ability.rb
elsif user.role == "admin"
can :manage, :all
cannot :update, Page, ["name == ?", "home"] do |page|
page.name == "home"
end
end
routes.rb (I'm using friendly_id to generate a slug from the :name attribute)
match '/:slug', :to => "pages#show", :as => :slug, :via => :get
root :to => 'pages', :controllers => "pages", :action => "show", :slug => "home"
pages_controller.rb (standard)
def update
#page = Page.find(params[:id])
respond_to do |format|
if #page.update_attributes(params[:page])
format.html { redirect_to #page, notice: 'Page was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
I must admit, I've read your question three times, and I think I have answers for you...
1 - Yes, I believe so. However, I'm not convinced your ability.rb code is correct. I'd aim for something closer to this:
cannot :update, Page do |page|
page.name == "home"
end
2 - If you do load_and_authorize_resource in your controller, that should be all you need, because that will load #page for you.
class PagesController < ApplicationController
load_and_authorize_resource
def update
respond_to do |format|
if #page.update_attributes(params[:page])
format.html { redirect_to #page, notice: 'Page was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
end
3 - To me, your route looks fine. That's likely the way I'd approach it.
So I'm testing one of my controller in RSPEC and I'm trying to test the whole update shenanigans. This is what i have in the RSPEC
describe 'PUT update' do
before :each do
#user = Factory(:user,name: "Lawrence Smith")
end
context "valid attributes" do
it "located the requested #user" do
put :update, :id => #user, user: Factory.attributes_for(:user)
assigns(:user).should eq(#user)
end
it "changes #user's attributes" do
put :update, :id=> #user.id, user: Factory.attributes_for(:user, name: "Larry Smith")
#user.reload
#user.name.should eq("Larry Smith")
end
end
And this is what i have in the controller
def update
#update and save
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
sign_in #user
format.json{render :json => #user ,:status => :created, :location => #user }
else
format.json { render :json => #user.errors, :status => :unprocessable_entity }
end
end
end
So apparently the the #user.reload doesn't really refresh the ActiveRecord, as my errors showed that the name has not been changed at all. Any idea what is wrong?
I don't know how you can pass object in get or post parameters. Anyways try like this
describe 'PUT update' do
before :each do
#user = Factory(:user,name: "Lawrence Smith")
end
context "valid attributes" do
it "located the requested #user" do
put :update, :id => #user, user: Factory.attributes_for(:user)
assigns(:user).should eq(#user)
end
it "changes #user's attributes" do
put :update, :id=> #user.id, :user_name => Factory.attributes_for(:user, name: "Larry Smith").name
#user.reload
#user.name.should eq("Larry Smith")
end
end
and this in controller
def update
#update and save
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(:name => params[:user_name])
sign_in #user
format.json{render :json => #user ,:status => :created, :location => #user }
else
format.json { render :json => #user.errors, :status => :unprocessable_entity }
end
end
I think you are getting what I explained here.
Thanks
i update class_name
/models/tipotercero.rb
class Tipotercero < ActiveRecord::Base
has_many :terceroclasificaciones
has_many :terceros , :class_name => "Terceroclasificacion"
end
/models/tercero.rb
class Tercero < ActiveRecord::Base
has_many :ciudades
has_many :terceroclasificaciones
has_many :tipoterceros, :class_name => "Terceroclasificacion"
end
class Terceroclasificacion < ActiveRecord::Base
belongs_to :tercero
belongs_to :tipotercero
attr_accessor :tercero_id, :tipotercero_id
end
/views/terceros/_form.html.erb
<div class="field">
<% for tipotercero in Tipotercero.all %>
<div>
<%= check_box_tag "tercero[tipotercero_ids][]", tipotercero.id, #tercero.tipoterceros.include?(tipotercero) %>
<%= tipotercero.nombre %>
</div>
<% end %>
</div>
the error is
uninitialized constant Tercero::terceroclasificacion
I have tried to follow the post
Rails 3 has_many :through Form but I could not find the error in my application
add terceros controller
/controllers/terceros_controller.rb
class TercerosController < ApplicationController
# GET /terceros
# GET /terceros.xml
def index
#terceros = Tercero.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #terceros }
end
end
# GET /terceros/1
# GET /terceros/1.xml
def show
#tercero = Tercero.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #tercero }
end
end
# GET /terceros/new
# GET /terceros/new.xml
def new
#tercero = Tercero.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #tercero }
end
end
# GET /terceros/1/edit
def edit
#tercero = Tercero.find(params[:id])
end
# POST /terceros
# POST /terceros.xml
def create
#tercero = Tercero.new(params[:tercero])
# #tercero.attributes = {'tipotercero_ids' => []}.merge(params[:tercero] || {})
respond_to do |format|
if #tercero.save
format.html { redirect_to(#tercero, :notice => 'Tercero was successfully created.') }
format.xml { render :xml => #tercero, :status => :created, :location => #tercero }
else
format.html { render :action => "new" }
format.xml { render :xml => #tercero.errors, :status => :unprocessable_entity }
end
end
end
# PUT /terceros/1
# PUT /terceros/1.xml
def update
#tercero = Tercero.find(params[:id])
respond_to do |format|
if #tercero.update_attributes(params[:tercero])
format.html { redirect_to(#tercero, :notice => 'Tercero was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #tercero.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /terceros/1
# DELETE /terceros/1.xml
def destroy
#tercero = Tercero.find(params[:id])
#tercero.destroy
respond_to do |format|
format.html { redirect_to(terceros_url) }
format.xml { head :ok }
end
end
end
edit 3
the page error is:
NameError in Terceros#new
Showing /home/andres/desarrollos/rubyonrails/proyecto/app/views/terceros/_form.html.erb where line #92 raised:
uninitialized constant Tercero::terceroclasificacion
Extracted source (around line #92):
89: <div class="field">
90: <% for tipotercero in Tipotercero.all %>
91: <div>
92: <%= check_box_tag "tercero[tipotercero_ids][]", tipotercero.id, #tercero.tipoterceros.include?(tipotercero) %>
93: <%= tipotercero.nombre %>
94: </div>
95: <% end %>
Trace of template inclusion: app/views/terceros/new.html.erb
4 edit
error to create tercero is:
NoMethodError in TercerosController#create
undefined method `type_cast' for nil:NilClass
Rails.root: /home/andres/desarrollos/rubyonrails/proyecto
Application Trace | Framework Trace | Full Trace
app/controllers/terceros_controller.rb:44:in `new'
app/controllers/terceros_controller.rb:44:in `create'
Request
Parameters:
{"tercero"=>{"identificacion"=>"1110465574",
"empresa"=>"hogar",
"tipo_identificacion"=>"2",
"direccion1"=>"dierccion",
"nombre"=>"carlos andres",
"direccion2"=>"123",
"ciudad_id"=>"2",
"telefono_fijo"=>"132233",
"telefono_movil"=>"123123",
"fecha_nacimiento(1i)"=>"2013",
"observaciones"=>"",
"fecha_nacimiento(2i)"=>"10",
"fecha_nacimiento(3i)"=>"17",
"representante_legal"=>"",
"tipotercero_ids"=>["1",
"2",
"3"],
"apellido1"=>"colonia",
"apellido2"=>"riveros",
"pagina_web"=>""},
"commit"=>"Crear Tercero",
"authenticity_token"=>"SeUoILctpNr9t6Lx8wSoHVTO5mjk0qJfnzJsb9Jtzao=",
"utf8"=>"✓"}
Sometimes other model cannot be derived from the association name just by Rails conventions and such strange errors occurs. You can pass class name like this:
has_many :terceroclasificaciones, :class_name => "Terceroclasificacion"
And btw, you can make your life easier just by using English names for your models and stuff. You do localization in your view anyways.
Try to remove this
attr_accessor :tercero_id, :tipotercero_id
I think you want it to be an attr_accessible but not attr_accessor
I have a form to update an item called post, but i need a different method than update because there are 2 ways to update the post, i have tried this in a lot of ways but i only get this error
No route matches "/topics/1/posts/35/completed"
the controller:
def completed
#post.download_remote_image
respond_to do |format|
if #post.save
format.html { redirect_to topic_path(#topic), :notice => t('.post_created') }
else
format.html { render :action => :edit }
end
end
end
the view part:
= form_for [#topic, #post], :url => completed_topic_post_path(#topic, #post) do |f|
the routes:
resources :topics do
resources :posts do
get 'complete', :as => :complete
post 'completed', :as => :completed
end
end
Thanks !!
:url => completed_topic_post_path(#topic, #post) needs to be :url => topic_post_completed_path(#topic, #post)
So I have devise setup to perform registration. After registration the user is redirected to profiles#new however I can't attach profile to current_user id
Actually it doesn't work at all. Here is what I have in my profiles_controller.rb
# POST /profiles
def create
#profile = current_user.Profile.new(params[:profile])
respond_to do |format|
if #profile.save
format.html { redirect_to(#profile, :notice => 'Profile was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
leading to undefined method `Profile' for #
So the User model has_one :profile ?
If so, you likely want:
#profile = current_user.profile.build(params[:profile])
Note that case ('profile' vs 'Profile') is important here.
I think that you should use
#profile = current_user.build_profile(params[:profile])
Check rails api here