please can somebody help me with this .i want to create a renew link which will update some of the fields in a table called members,am using rails 3 and i have created my action and the corresponding view but i still have an error that states
"undefined method'renew_member_path' for #<#:0xb66bcae0>"
below is the action i created in the members_controller
Class MembersController
def renew
#member = Member.find(params[:id])
respond_to do |format|
if #member.renew_attributes(params[:member])
format.html { redirect_to(#member, :notice => 'Member was succesfully Renewed.'}
format.xml {head :ok }
else
format.html { render :action => 'renew'}
format.xml { render :xml => #member.errors, :status => :unprocessable_entity}
end
end
end
I created a view called renew.html.erb
Your route is not set. You need to update your routes.rb file to something like this:
match 'members/renew' => 'members#renew', :as => :renew_member
Related
I am still a bit new to RoR, and am using scaffolding to generate CRUD interfaces for data.
I am using devise for user authentication, and want to allow a user that owns a specific entry to edit or delete, but protect that data from other users. However, I would like to allow a different user to revise or create new versions.
So if a user that attempts to edit should appear as if they are editing, but when they submit, the controller should actually generate a new entry (and potentially specify the parent_id of the entry it derived from).
Any help on implementation is greatly appreciated.
Also look into Ancestry, it's a really nice library to help with versioning.
Here is my solution that I came up with. I am a ruby newb, so I assume that I can just call the create function with the same params but wasn't sure how to do that, so I just duplicated code:
def update
#section = Section.find(params[:id])
if #section.owner == current_user.id
respond_to do |format|
if #section.update_attributes(params[:section])
format.html { redirect_to(#section, :notice => 'Section was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #section.errors, :status => :unprocessable_entity }
end
end
else
# REVISE
#childsection = Section.new(params[:section])
respond_to do |format|
if #childsection.save
format.html { redirect_to(#childsection, :notice => 'Section was successfully revised.') }
format.xml { render :xml => #childsection, :status => :created, :location => #childsection }
else
format.html { render :action => "new" }
format.xml { render :xml => #childsection.errors, :status => :unprocessable_entity }
end
end
end
end
I'm using Rails 3 for this one. I've got a collections model, a user model and an intermediate subscription model. This way a user can subscribe to multiple collections, with a particular role. However, I don't want a user to be able to subscribe to the same collection twice.
So in my Subscription model I've got something like:
validate :subscription_duplicates
def subscription_duplicates
self.errors.add_to_base "This user is already subscribed" if Subscription.where(:user_id => self.user.id, :collection_id => self.collection.id)
end
However this seems ugly. Also, it breaks when I want to do something like the following in my collection controller:
def create
#collection = Collection.new(params[:collection])
#collection.subscriptions.build(:user => current_user, :role => Subscription::ROLES['owner'])
#collection.save
respond_with(#collection)
end
When I do the build the subscription does not have an id so I get a "Called id for nil" error.
Thanks for any guidance!
use validates_uniqueness_of
validates_uniqueness_of :user_id, :scope => :collection_id
First of all, your create action should always test if the object was saved, and if not then handle that (usually by re-rendering the new/edit page and showing the errors to the user).
A standard sort of create action would look like this (for a #post in this case):
def create
#post = Post.new(params[:post])
#created = #post.save
respond_to do |format|
if #created
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to #post }
format.xml { render :xml => #post, :status => :created, :location => #post }
format.js
else
format.html { render :action => :new } #or edit or wherever you got here from
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
format.js
end
end
end
Shingara's approach to avoiding duplicates should work fine for you.
I'm diving into RoR and as I'm going through the tutorials, scaffolds, and docs, I'm coming across some code that confuses me. For example, I just read up on the 'redirect_to' method, but the guide I read didn't cover the example of redirecting to an instance var, such as the code that is generated in a typical scaffold...
# POST /articles
# POST /articles.xml
def create
#article = Article.new(params[:article])
respond_to do |format|
if #article.save
format.html { redirect_to(#article, :notice => 'Article 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
In the statement format.html { redirect_to(#article, :notice => 'Article was successfully created.') }, the code is redirecting to the instance var article, which causes a 'redirect_to' the show method in the current controller. Why does this cause it to redirect to the show method?
Thanks so much for your help!
Why does this cause it to redirect to the show method?
Because if you don't specify particular action, Rails assumes you want to 'show' object. If you have another action in mind, try
redirect_to :action => :do_something, :id => #article
When I:
self.save
or
save!
in a model it automatically redirects me to the show view for that given model. How can I override this? I want to save the model and then go to another action/view in the same controller.
In particular, I have a process where I save a members details, and then I want to continue the process by going to the next page, e.g. payment page, that uses the id of the saved model.
In your controller you might have a block like:
def create
#user = User.new(params[:place])
respond_to do |format|
if #user.save
format.html { redirect_to(#user, :notice => 'User was successfully created.') }
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
You can change the target of the redirect_to (after format.html) from here - at present it is directing you to the record for that user, ie. #user. Take a look at http://api.rubyonrails.org/classes/ActionController/Base.html for a bit more info.
You likely have a block like this in your create/update methods:
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
So if your instance variable is named #post, and it's redirecting to the show view for the post after it saves, all you have to do is change the "redirect_to(#post, ..." part to whatever you want. Say you wanted to redirect to the root of your site - you could instead have
redirect_to(root_path, :notice => 'Post was successfully created.')
In your particular case, you could use something like this if you have your routes set up:
redirect_to(payment_page_path(#post), :notice => 'Post was successfully created.')
Hope that helps!
if you call save from your Model you will not be directed anywhere, it just does a direct model access save to the database. Your redirections are described in your controller in your create and update actions. you can find a list of routes by running rake routes and then pick the path you want your app to render when you save your model instance. you may have a route called payment_path which might look like this in your controller
map.payment :controller => :payments_controller, :action => index
and you would say in your create action
def create
if #item.save(params[:item])
redirect_to payment_path
else
flash[:error] = "there was a problem"
render :action => buy
end
end
if you need to pass a param, like user id to your route, then you need to include that in the path parameters
redirect_to payment_path(#user) #=> automagically finds the id of active record models
Simple RoR question...I am learning ROR and am making a simple voting app. The candidates are listed in a table and have upvote/downvote links next to their name. I am trying to make it so all the user does is click the link, the vote count is updated, and they are redirected to the initial page. I am not using scaffolding. For some reason this action is not doing anything close to what I want:
def upvote
#name = Name.find(params[:id])
#name[:votes] += 1
respond_to do |format|
if #name.update_attributes(params[:name])
flash[:notice] = 'Candidate was upvoted'
format.html = { redirect_to :action => "index" }
format.xml = { head :ok }
else
format.html = { render :action => "index" }
format.xml = { render :xml => #name.errors, :status => :unprocessable_entity }
end
end
end
I do have the link in the view calling the correct action, it's trying to call :show, though.
please don't judge me too harshly lol...
The update_attributes method is generally used to set the fields of an ActiveRecord object from a form POST. The fields would be found as the hash params[:name], e.g. params[:name][:votes].
If you are clicking on a link to call the upvote method, then you are just doing a GET request. All you need to do is call #name.save to save the record.
def upvote
#name = Name.find(params[:id])
#name[:votes] += 1
respond_to do |format|
if #name.save
flash[:notice] = 'Candidate was upvoted'
format.html = { redirect_to :action => "index" }
format.xml = { head :ok }
else
format.html = { render :action => "index" }
format.xml = { render :xml => #name.errors, :status => :unprocessable_entity }
end
end
end
EDIT: From the comments, we also determined that the routes were set up improperly and that the link_to code in the view needed to include #name.id.
Typically the RESTful URL that maps to show is:
my_resource/id
So, e.g.,
candidates/1
Just at a guess, I'll bet if you look in config/routes.rb, you'll find something like:
map.resources :candidates
Where my_resource is the name of your controller. If you are going to use this kind of routing, then how does the resource provide upvoting? The custom method seems wise in this case, so:
map.resources :candidates, :collection => { :upvote => :post }
If you run
rake routes | grep candidate
before and after, you can see what's been added. Hope this helps.