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 %>
Related
after upgrading to rails 3.2.8 my private methods that passes mass assignment in rails 3.2.6 no longer passes i keep getting the mass assignment error.
my controller is
class AddressesController < BaseController
# GET /addresses
# GET /addresses.json
def index
#address = Address.new
form_info
respond_to do |format|
format.html # index.html.erb
format.json { render json: #addresses }
end
end
# GET /addresses/1
# GET /addresses/1.json
def show
#address = Address.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #address }
end
end
# GET /addresses/new
# GET /addresses/new.json
def new
#address = Address.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #address }
end
end
# GET /addresses/1/edit
def edit
#address = Address.find(params[:id])
end
# POST /addresses
# POST /addresses.json
def create
if params[:address].present?
#address = current_user.addresses.new(params[:address])
#address.default = true if current_user.default_shipping_address.nil?
#address.save_default_address(current_user, params[:address])
elsif params[:address_id].present?
#address = current_user.addresses.find(params[:address_id])
end
respond_to do |format|
if #address.id
update_order_address_id(#address.id)
format.html { redirect_to(orders_url, :notice => 'Address was successfully created.') }
else
form_info
format.html { render :action => "index" }
end
end
end
# PUT /addresses/1
# PUT /addresses/1.json
def update
#address = Address.find(params[:id])
respond_to do |format|
if #address.update_attributes(params[:address])
format.html { redirect_to #address, notice: 'Address was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
# DELETE /addresses/1
# DELETE /addresses/1.json
def destroy
#address = Address.find(params[:id])
#address.destroy
respond_to do |format|
format.html { redirect_to addresses_url }
format.json { head :no_content }
end
end
private
def update_order_address_id(id)
session_order.update_attributes(
:address_id => id
)
end
def form_info
#addresses = current_user.addresses
end
end
after creating an address i expect it to perform update_order_address_id(id) method but it keeps telling me
Can't mass-assign protected attributes: address_id
All this started after upgrading to rails 3.2.8. Does any body know how i can fix this please or any suggestions towards this.
Try to add this line to the model
attr_accessible :address_id
https://stackoverflow.com/a/4538861/643500
Edit:
Not sure if you read this
class AccountsController < ApplicationController
include ActiveModel::MassAssignmentSecurity
attr_accessible :first_name, :last_name
attr_accessible :first_name, :last_name, :plan_id, :as => :admin
def update
...
#account.update_attributes(account_params)
...
end
protected
def account_params
role = admin ? :admin : :default
sanitize_for_mass_assignment(params[:account], role)
end
end
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html
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
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)
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>
I have two controllers: projects and stages.
Projects has many stages and stages belongs to projects. I want when you click on the name of the project (i.e. the projects show action), for it to show all the stages related to that project.
How do I do that ?
All of the relevant code can be found below:
Stages Controller
class StagesController < ApplicationController
filter_resource_access
# GET /stages
# GET /stages.xml
def index
#stages = Stage.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #stages }
end
end
# GET /stages/1
# GET /stages/1.xml
def show
#stage = Stage.find(params[:id])
##project = Project.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #stage }
end
end
# GET /stages/new
# GET /stages/new.xml
def new
#stage = Stage.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #stage }
end
end
# GET /stages/1/edit
def edit
#stage = Stage.find(params[:id])
end
# POST /stages
# POST /stages.xml
def create
#stage = current_user.stages.create(params[:stage])
##stage = Stage.new(params[:stage])
respond_to do |format|
if #stage.save
format.html { redirect_to(#stage, :notice => 'Stage was successfully created.') }
format.xml { render :xml => #stage, :status => :created, :location => #stage }
else
format.html { render :action => "new" }
format.xml { render :xml => #stage.errors, :status => :unprocessable_entity }
end
end
end
# PUT /stages/1
# PUT /stages/1.xml
def update
#stage = Stage.find(params[:id])
respond_to do |format|
if #stage.update_attributes(params[:stage])
format.html { redirect_to(#stage, :notice => 'Stage was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #stage.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /stages/1
# DELETE /stages/1.xml
def destroy
#stage = Stage.find(params[:id])
#stage.destroy
respond_to do |format|
format.html { redirect_to(stages_url) }
format.xml { head :ok }
end
end
end
Stages model:
# == Schema Information
# Schema version: 20101124095341
#
# Table name: stages
#
# id :integer not null, primary key
# project_id :integer
# created_at :datetime
# updated_at :datetime
# user_id :integer
# name :string(255)
# stage_num :integer
class Stage < ActiveRecord::Base
belongs_to :projects
#has_and_belongs_to_many :users
has_many :uploads
has_many :comments
end
Projects Model
# == Schema Information
# Schema version: 20101117094659
#
# Table name: projects
#
# id :integer not null, primary key
# name :string(255)
# description :string(255)
# designer_id :integer
# client_id :integer
# notified :boolean
# created_at :datetime
# updated_at :datetime
# user_id :integer
class Project < ActiveRecord::Base
belongs_to :user
has_many :stages
has_many :uploads
has_many :comments
#before_validation { |project| project.user = Authorization.current_user unless project.user }
end
Project Controller
class ProjectsController < ApplicationController
filter_resource_access
# GET /projects
# GET /projects.xml
def index
#projects = current_user.projects
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])
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
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])
end
# POST /projects
# POST /projects.xml
def create
#project = current_user.projects.create(params[:project])
respond_to do |format|
if #project.save
format.html { redirect_to(#project, :notice => 'Project was successfully created.') }
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])
format.html { redirect_to(#project, :notice => 'Project was successfully updated.') }
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
Projects Show View
<p id="notice"><%= notice %></p>
<br />
<% #projects.each do |project| %>
<% #stages.each do |stage| %>
<tr>
<td><%= link_to stage.name, stage %> | </td>
<td><%= stage.stage_num %> | </td>
<td><%= link_to 'Show', stage %></td>
<td><%= link_to 'Edit', edit_stage_path(stage) %></td>
<td><%= link_to 'Destroy', stage, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
<% end %>
<% if permitted_to? :create, Stage.new %>
<%= link_to 'New Stage', new_stage_path %>
<% end %><br /><br />
<%= link_to 'Edit', edit_project_path(#project) %> |
<%= link_to 'Back', projects_path %>
There are many ways to do this. The easiest way to accomplish this with your existing code is to change the projects show view page.
replace this:
<% #projects.each do |project| %>
<% #stages.each do |stage| %>
with:
<% #project.stages.each do |stage| %>
Then, you would use the "index" view to show all the projects and the "show" view would be to show project specifics (which would include stages)