Rails app generating wrong :id in parent controller - ruby-on-rails-3

I am creating a very basic rails app for the first time with 2 resources, Departments(depts) and Members. I believe I have used nested resources correctly, but for some reason after running rails server, the :id for the parent resource is not being generated/passed correctly. Root is the depts#index and from here I can do new and edit using _form.haml rendered in the new and edit views. However, when I do /depts/3 I get error with "can't find dept with id=3". Clicking through to edit from index gives me /depts/63/edit in the URL - I'm not sure where this id=63 has come from. Trying to get to 'show' action by typing /dept/63 in the URL does not work. I created Depts on it's own at first, got it working with all actions and views, something has gone wrong since I added Members resource.
routes.rb
resources :depts do
resources :members
end
depts_controller.rb
def index
#depts = Dept.all
respond_to do |format|
format.html
format.json { render :json => #depts }
end
end
def show
#dept = Dept.find(params[:dept_id])
respond_to do |format|
format.html
format.json { render :json => #dept }
end
end
def new
#dept = Dept.new(params[:dept])
respond_to do |format|
format.html
format.json { render :json => #dept }
end
end
def create
#dept = Dept.new(params[:dept])
respond_to do |format|
if #dept.save
format.html { redirect_to :action => 'index' }
format.json { render :json => #dept }
else
format.html { render :action => 'new' }
format.json { render :json => #dept }
end
end
end
def edit
#dept = Dept.find(params[:id])
end
def update
#dept = Dept.find(params[:id])
respond_to do |format|
if #dept.update_attributes(params[:dept])
format.html { redirect_to :action => 'index'}#, :id => #dept }
format.json { render :json => #dept }
else
format.html { redirect_to :action => 'edit' }
format.json { render :json => #dept }
end
end
end
def destroy
#dept = Dept.find(params[:id])
#dept.destroy
respond_to do |format|
format.html { redirect_to :action => 'index' }
format.json { render :json => #dept }
end
end
end
show.haml
%p= #dept.name
%p= link_to "back", {:action => 'index'}
index.haml
%h1 DEPARTMENTS
%ol
- #depts.each do |d|
%li= link_to d.name
%p= link_to 'edit department', edit_dept_path(d)
%p= link_to 'get rid of department!', d, :method => :delete, :id => d.id
%br
%p= link_to "ADD A NEW DEPARTMENT", new_dept_path

in show method change:
#dept = Dept.find(params[:dept_id])
to:
#dept = Dept.find(params[:id])
and in new method change:
#dept = Dept.new(params[:dept])
to just:
#dept = Dept.new

Related

respond_with and how to set redirect location?

I have the following that update user profile. It does perfectly fine with base url (http://domain_name.com/users/).
def update
#user = User.find(params[:id])
respond_with #user do |format|
if #user.update_attributes(params[:user])
if current_user.becomes(User) == #user
sign_in(#user, :bypass => true)
end
flash[:notice] = 'User was successfully updated.'
format.html { redirect_to #user }
format.json { render :status => :ok }
else
format.html { render :action => 'edit' }
format.json { render :status => :bad_request }
end
end
end
Now I want to move it into admin namespace (http://domain_name.com/admin/users/). And what I try is to change
redirect_to #user
to
redirect_to admin_user_path(#user)
then I got:
def update
#user = User.find(params[:id])
#respond_with(#user) do |format|
respond_with(#user, :location => admin_user_path(#user)) do |format|
if #user.update_attributes(params[:user])
if current_user.becomes(User) == #user
sign_in(#user, :bypass => true)
end
flash[:notice] = 'User was successfully updated.'
format.html { redirect_to admin_user_path(#user) }
format.json { render :status => :ok }
else
format.html { render :action => 'edit', :location => edit_admin_path(user) }
format.json { render :status => :bad_request }
end
end
end
But it does not work. I also try to change
respond_with(#user) do |format|
to something like
respond_with(#user, :location => admin_user_path(#user)) do |format|
But it doesn't work too. Can anyone have some experience, please give me some advice or explanation.
Thanks!
I do believe the following line:
respond_with(#user, :location => admin_user_path(#user)) do |format|
Seems a bit odd to me. I would've thought this should be respond_with(#user) do |format|
Also take a read of the following: Ryan's Scraps - Cleaner RESTful Controllers / respond_with. Ryan states the following under Pre-Action Overriding:
It’s also possible to override standard resource handling by passing in a block to respond_with specifying which formats to override for that action.
From this you will see that the formats that are to be overrided are declared at the top of the class using respond_to

form_for update method

On a page I have task listed out. I want to put a form for that task as an update to complete that task. I have the following code as a form_for:
<%= form_for :event, :action => :update, :id => event.id do |f| %>
<%= f.check_box :complete %>
<%= f.submit 'Complete %>
<% end %>
With this code I want it to edit the event with the id in the url and complete the event. What it does it creates a new event instead. Any ideas?
Event Controller:
class EventsController < ApplicationController
layout 'events', :except => 'edit'
# GET /events
# GET /events.json
def index
#events = Event.order("events.initials ASC, events.priroty ASC")
#archived = CompleteEvent.order("complete_events.created_at ASC")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #events }
end
end
# GET /events/1
# GET /events/1.json
def show
#event = Event.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #event }
end
end
# GET /events/new
# GET /events/new.json
def new
#event = Event.new
#users = ['BG', 'BD', 'MB', 'AF', 'RA', 'JM']
#name = ['Brad Garrison', 'Brian Davis', 'Matt Broach', 'Alan McFarland', 'Russell Anderson', 'Jason Milam']
respond_to do |format|
format.html # new.html.erb
format.json { render json: #event }
end
end
# GET /events/1/edit
def edit
#event = Event.find(params[:id])
#users = ['BG', 'BD', 'MB', 'AF', 'RA', 'JM']
#name = ['Brad Garrison', 'Brian Davis', 'Matt Broach', 'Alan McFarland', 'Russell Anderson', 'Jason Milam']
end
# POST /events
# POST /events.json
def create
#event = Event.new(params[:event])
respond_to do |format|
if #event.save
user = #event.name
Notifier.task_created(user).deliver
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# PUT /events/1
# PUT /events/1.json
def update
#event = Event.find(params[:id])
#save = #event.update_attributes(params[:event])
#complete = CompleteEvent.new(:initials => #event.initials, :name => #event.name, :event_name => #event.event_name, :complete => #event.complete, :event_description => #event.event_description, :comment => #event.comment)
respond_to do |format|
if #event.update_attributes(params[:event])
if #event.complete == true
user = #event.name
#save
#complete
#complete.save
#event.destroy
format.html { redirect_to :controller => :events, :action => :index}
format.json { head :no_content }
elsif #event.complete == false
Notifier.task_updated(user).deliver
format.html { redirect_to :controller => :events, :action => :index}
format.json { head :no_content }
end
end
end
end
# DELETE /events/1
# DELETE /events/1.json
def destroy
#event = Event.find(params[:id])
#event.destroy
respond_to do |format|
format.html { redirect_to events_url }
format.json { head :no_content }
end
end
end
In edit.html.erb (or your partial that is rendered in edit.html.erb) use:
<%= form_for #event do |f| %>
You generally do not need to specify the action, since it is inferred from the URI path, and Rails knows the id for the model object is #event.id.
What I was missing was that my form was in a loop. Therefore when I was calling the form_for #event it couldn't see outside of that loop. I had the function take on the variable of event.
<% #events.each do |event| %>
......
......
<% form_for event do |f| %>
.....
<% end %>

undefined method for nil:NilClass

upload controller
def create
#upload = #order.uploads.build(params[:uploadtwo])
respond_to do |format|
if #upload.save
format.html { redirect_to root_path, :notice => 'File was successfully uploaded.' }
format.json { render :json => #upload, :status => :created, :location => #upload }
else
format.html { render :action => "new" }
format.json { render :json => #upload.errors, :status => :unprocessable_entity }
end
end
upload model
belongs_to :order
order model
has_many :uploads
i get error [NoMethodError in UploadtwosController#create ], [undefined method `uploads' for nil:NilClass]
anybody knows what am not doing?
Just declaring belongs_to :order in your Upload model does not mean that #order will automatically be defined in the controller. Perhaps what you want is a before_filter in the controller which will set #order?

Rails 3 - Atom Feed Help Needed?

Am having trouble getting the Atom feed function to work on my blog. I am using the Kaminari plug-in to paginate my articles - 6 per page. With the code below, when a user clicks on the RSS Feed image they are asked to log-in instead of subscribing to the feed! Any help would be appreciated with this issue...
application.html.erb
page head <%= auto_discovery_link_tag(:atom, feed_path, { :title => "My ATOM Feed" }) %>
page body <%= image_tag("feed.png", {:alt => 'Atom feed', :class=>"feed"}) %>Subscribe
routes.rb
match '/feed' => 'articles#feed', :as => :feed, :defaults => { :format => 'atom' }
articles_controller
class ArticlesController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show]
# GET /articles
# GET /articles.xml
# display articles on the home page
def index
#articles = Article.published.page(params[:page]).per(6).ordered
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #articles }
format.atom { render :atom => #articles }
end
end
# GET /articles/1
# GET /articles/1.xml
def show
#article = Article.find(params[:id])
#comment = Comment.new(:article=>#article)
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #article }
end
end
# GET /articles/new
# GET /articles/new.xml
def new
#article = Article.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #article }
end
end
# GET /articles/1/edit
def edit
#article = Article.find(params[:id])
authorize! :edit, #article
end
# POST /articles
# POST /articles.xml
def create
#authorize! :create, #article
#article = Article.new(params[:article])
#article.user_id = current_user.id
respond_to do |format|
if #article.save
format.html { redirect_to(#article, :notice => 'Worry was successfully created.') }
format.xml { render :xml => #article, :status => :created, :location => #article }
else
format.html { render :action => "new" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
# PUT /articles/1
# PUT /articles/1.xml
def update
#article = Article.find(params[:id])
authorize! :update, #article
respond_to do |format|
if #article.update_attributes(params[:article])
format.html { redirect_to(#article, :notice => 'Worry was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #article.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /articles/1
# DELETE /articles/1.xml
def destroy
#article = Article.find(params[:id])
authorize! :destroy, #article
#article.destroy
respond_to do |format|
format.html { redirect_to(articles_url) }
format.xml { head :ok }
end
end
end
views/articles/feed.atom.builder
atom_feed :language => 'en-US' do |feed|
feed.title "mysite.com"
feed.updated(#articles.blank? ? Time.now : #articles.first.created_at)
#articles.each do |article|
feed.entry article, :published => article.accepted do |entry|
entry.title article.title
entry.author do |author|
author.name article.user.fullname
end
end
end
end
Update this line in your articles_controller:
before_filter :authenticate_user!, :except => [:index, :show]
... with:
before_filter :authenticate_user!, :except => [:index, :show, :feed]
This will prevent the request for authentication.
Two suggestions:
1) Add :url and :root_url to the atom_feed call.
2) Change:
feed.updated #articles.first.created_at
to:
feed.updated(#articles.blank? ? Time.now : #articles.first.created_at)

Howto assign an ordinary user as superuser or admin

I was following the tutorial at http://www.logansbailey.com/ and modified it to enable an unregistered person to be able to register with a username, email and password.
I already enabled a logged in user to modify his/her email and password but not the username.
What I want to add is:
1) to enable a logged in user to be able to see/reach his/her username and email,
2) to enable a user with admin_flag set (I handled this in the sql table and created the user) to be able to see/modify all user records.
I modifyed the app/cotrollers/user_controller.rb like this:
class UsersController < ApplicationController
before_filter :is_user, :only => [:index, :show, :edit, :update, :destroy]
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
def edit
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'Registration successful.'
format.html { redirect_to(:controller => 'home', :action => 'tutorial') }
format.xml { render :xml => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #user.update_attributes(params[:user])
flash[:notice] = 'Your profile was successfully updated.'
format.html { redirect_to(:controller => 'home', :action => 'index') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
def is_user
if User.exists?(params[:id])
#user = User.find(params[:id]);
if current_user.admin_flag == true
flash[:notice] = 'Welcome Admin'
end
if !current_user || current_user.id != #user.id
flash[:notice] = 'You do not have access to that page'
redirect_to(:controller => 'home', :action => 'index')
end
else
flash[:notice] = 'You do not have access to that page'
redirect_to(:controller => 'home', :action => 'index')
end
end
end
The file app/models/user.rb is:
class User < ActiveRecord::Base
acts_as_authentic
end
And I can confirm that the admin_flag set user is get correctly since the file app/views/layouts/application.html.erb containing:
<div id="admin">
<% if current_user %>
<% if current_user.admin_flag == true %> |
<%= link_to "Users", users_path %>
<% end %>
<% end %>
</div>
correctly displays the 'Users' link when I log in as the admin.
Now the problem is that I can't get the show all users, edit other users etc.. functionality. As the admin, I can show and modify the admin user just like all the other ordinary users, meaning I can't modify the username, too.
What may be wrong here?
When you added a boolean attribute admin to user in the right way, the Rails should add question-mark method admin? in User model. It's not important but for convenience.
On every method you want to protect from unwanted actions use before_filter:
class UsersController < ApplicationController
before_filter :admin_user, :only => :destroy
before_filter :correct_user, :only => [:edit, :update]
def destroy
end
...
private
def admin_user
redirect_to(root_path) unless current_user.admin?
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user) || current_user.admin?
end
end
In views more convenient to use current_user.admin?
<div id="admin">
<% if current_user.admin? %>
<%= link_to "Users", users_path %>
<% end %>
</div>