Using Best_in_Place to edit attributes - ruby-on-rails

I am using the Best_in_Place gem to make areas on my site in place editable. I have two models: Student and Education, with the relationship being that each Student has_many Educations. I have the Best_in_place functionality working when editing attributes that are directly in the Student model, such as
<%=best_in_place #student, :name =>
However, I can't get it to update the attributes of an education.. with a line like
<%=best_in_place #education, :college =>
in the view of students/show,
I get the error
Started PUT "/educations" for 127.0.0.1 at 2012-03-25 13:06:57 -0400
ActionController::RoutingError (No route matches [PUT] "/educations")
and not only does it not work, the editable spot disappears completely. I can't figure out what's causing the problem, everything seems to be the same for both models/controllers. My routes are very simple:
resources :students
resources :educations
root :to => 'pages#home'
devise_for :students
as are my controllers:
def update
#student = Student.find(params[:id])
respond_to do |format|
if #student.update_attributes(params[:student])
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
vs
def update
#education = Education.find(params[:id])
respond_to do |format|
if #education.update_attributes(params[:education])
format.html { redirect_to #education, notice: 'Education was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #education.errors, status: :unprocessable_entity }
end
end
end
If I rake routes, I get:
educations GET /educations(.:format) educations#index
POST /educations(.:format) educations#create
new_education GET /educations/new(.:format) educations#new
edit_education GET /educations/:id/edit(.:format) educations#edit
education GET /educations/:id(.:format) educations#show
PUT /educations/:id(.:format) educations#update
DELETE /educations/:id(.:format) educations#destroy
students GET /students(.:format) students#index
POST /students(.:format) students#create
new_student GET /students/new(.:format) students#new
edit_student GET /students/:id/edit(.:format) students#edit
student GET /students/:id(.:format) students#show
PUT /students/:id(.:format) students#update
DELETE /students/:id(.:format) students#destroy
Any pointers would be a huge help.

Two Things:
Your view syntax is off. You're closing your tags with => instead of %>. So try this instead:
<%=best_in_place #student, :name %>
<%=best_in_place #education, :college %>
Try updating the respond_to blocks for format.json to respond_with_bip(#student). That should enable the user to edit via javascript, while leaving the user on the page to see their updates via AJAX.
See ReadMe for best_in_place Controller response with respond_with_bip
See updates below:
def update
#student = Student.find(params[:id])
respond_to do |format|
if #student.update_attributes(params[:student])
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { respond_with_bip(#student) }
else
format.html { render action: "edit" }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
def update
#education = Education.find(params[:id])
respond_to do |format|
if #education.update_attributes(params[:education])
format.html { redirect_to #education, notice: 'Student was successfully updated.' }
format.json { respond_with_bip(#education) }
else
format.html { render action: "edit" }
format.json { render json: #education.errors, status: :unprocessable_entity }
end
end
end

Related

How to add different edit/update method into rails controller?

The controller:
def edit
end
def update
respond_to do |format|
if #item.update(item_params)
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
I want to add another methods like this. For updating only 1 column of item and i want to dont show other columns to user.
I have all neccesary views.
def another_edit
end
def another_update
respond_to do |format|
if #item.update(params[:item].permit(:amount))
format.html { redirect_to #item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: #item }
else
format.html { render :edit }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
I thought my routes are wrong. Then tried
resources :items do
collection do
get 'add', on: :edit
end
end
and
get 'items/another_edit'
Is it possible or not? Please help me.
You need to add those endpoints in routes as "member" (not collection):
resources :items do
get :another_edit, on: :member
put :another_update, on: :member
end
Then routes will be built with "id" parameter inside.

Bad Redirect On Create Method - Rails 4

I am trying to change the redirect when I create a listing, but I keep getting a No route matches {:action=>"manage_photos", :controller=>"listings"} missing required keys: [:id]. What am I missing? My route is nested and there is a manage_photos method in my controller. Not sure where to go from here.
routes.rb
resources :listings do
member do
get 'like'
get 'unlike'
get 'duplicate'
get 'gallery'
delete 'gallery' => 'listings#clear_gallery'
get 'manage_photos'
get 'craigslist'
get "add_to_collection"
get 'request_photos'
get 'rsvp'
end
end
rake routes:
manage_photos_listing GET /listings/:id/manage_photos(.:format) listings#manage_photos
listings_controller:
create method:
def create
#listing = Listing.new(listing_params)
respond_to do |format|
if #listing.save
format.html { redirect_to manage_photos_listing_path, notice: 'Listing was successfully created.' }
format.json { render json: #listing, status: :created, location: #listing }
else
format.html { render action: "new", notice: "Correct the mistakes below to create the new listing" }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
manage_photos method:
def manage_photos
#listing = Listing.find(params[:id])
end
error:
Since it is a nested resource you have to add the id of the parent element. Try:
manage_photo_listing(#listing)
so it can actually use the id of #listing and build the route

Nested Routes - Broken Form, NoMethodError - undefined method

To learn Rails, I'm working on a simple calendar app. To get started, I created two scaffolds and the proper associations/routes:
calendars
content_items
app/models/calendar.rb
class Calendar < ActiveRecord::Base
has_many :content_items
end
app/models/content_item.rb
class ContentItem < ActiveRecord::Base
belongs_to :calendar
end
routes.rb
resources :calendars do
resources :content_items
end
controllers/content_items_controller.rb
def create
#content_item = ContentItem.new(content_item_params)
#calendar = Calendar.find(params[:calendar_id] )
respond_to do |format|
if #content_item.save
format.html { redirect_to calendar_content_item_path(#calendar,#content_item), notice: 'Content item was successfully created.' }
format.json { render :show, status: :created, location: #content_item }
else
format.html { render :new }
format.json { render json: #content_item.errors, status: :unprocessable_entity }
end
end
end
When I created the nested routes, I began to run into errors when trying to create new content_items. Whenever I submit the form, I get this error:
NoMethodError in ContentItems#create
undefined method `content_items_path'
The error is coming from:
views/content_items/index.html.erb
<%= form_for [#calendar, #content_item] do |f| %>
UPDATE
Using the code posted below by #Gaurav GuptA fixed the form issue, but led to a new errror. Whenever I visit /calendars/1/content_items, I recieve an error - but only after creating an entry. With an empty database, it works fine.
ActionController::UrlGenerationError
No route matches {:action=>"show", :calendar_id=>#, :controller=>"content_items", :format=>nil, :id=>nil} missing required keys: [:id]
I believe this is because the content_item is being saved without a calendar_id. How do I set the content_item to save with the calendar_id it belongs to?
UPDATE 2
It now saves with a calendar_id, but when an item is saved, the links for edit/shpw/destroy throw errors.
No route matches {:action=>"show", :calendar_id=>#<ContentItem id: 1, , content_type: "Test", content_text: "Tetst\r\n", calendar_id: 1, created_at: "2015-05-26 07:06:42", updated_at: "2015-05-26 07:06:42", content_image_file_name: nil, content_image_content_type: nil, content_image_file_size: nil, content_image_updated_at: nil>, :controller=>"content_items", :format=>nil, :id=>nil} missing required keys: [:id]
It highlights this part of the file:
<td><%= link_to 'Show', calendar_content_item_path(content_item) %></td>
GitHub link: https://github.com/JeremyEnglert/baked
Try to change your create action of content_items_controller as:
def create
#calendar = Calendar.find(params[:calendar_id] )
#content_item = #calendar.content_items.new(content_item_params) #Edit
respond_to do |format|
if #content_item.save
format.html { redirect_to calendar_content_item_path(#calendar,#content_item), notice: 'Content item was successfully created.' }
format.json { render :show, status: :created, location: #content_item }
else
format.html { render :new }
format.json { render json: #content_item.errors, status: :unprocessable_entity }
end
end
end
Hope this will work for you.
Ok so with the routes you have:
resources :calendars do
resources :content_items
end
You get a path like this for example:
/calendars/50
/calendars/50/content_items/77
Which are then routed to:
app/controllers/calendars_controller.rb
app/controllers/content_items_controller.rb
Your error comes from your create action in your ContentItemsController. The params you are posting to the action include your calendar id "calendar_id"=>"1"
but nothing is there to receive it.
You need to get the instance of Calendar associated with the item you are creating.
#calendar = Calendar.find(params[:calendar_id] )
Then after you save #content_item pass to the calendar_content_item_path (as indicated in your routes) both objects:
format.html { redirect_to calendar_content_item_path(#calendar,#content_item), notice: 'Content item was successfully created.' }
In your create method in the ContentItemsController should look like this:
def create
#calendar = Calendar.find(params[:calendar_id] )
#content_item = #calendar.content_items.build(params[:content])
respond_to do |format|
if #content_item.save
format.html { redirect_to calendar_content_item_path(#calendar,#content_item), notice: 'Content item was successfully created.' }
format.json { render :show, status: :created, location: #content_item }
else
format.html { render :new }
format.json { render json: #content_item.errors, status: :unprocessable_entity }
end
end
end
I have also noticed that you are passing the calendar id to your strong params. That would through an error since the calendar's id is not assigned by the user.
You can read more on Strong Parameters.

Nested Routes in Rails 3.2.3

I am trying to create nested routes for a project that has many boards.
First I am creating a link to a new board:
<%= link_to 'New Board', new_project_board_path(#project) %>
In routes.rb I just nested the restful routes:
resources :projects do
resources :boards
end
And in the boards controller I adapted the new and create action as follows:
def new
#project = Project.find(params[:project_id])
#board = #project.boards.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
def create
#project = Project.find(params[:project_id])
#board = #project.boards.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
At least I also changed the _form.html.erb into:
<%= form_for([#project, #board]) do |f| %>
etc.
My problem starts when I click the button create board (so the new action is executed) it says no route matches. I guess it has to do with the create action because it doesn't get the id of the project anymore? I really don't know what else to change and where.
Seems your error is here
format.html { redirect_to #board, notice: 'Board was successfully created.' }
You don't have non-nested :boards resources, do you? Try to change this line to
format.html { redirect_to [#project, #board], notice: 'Board was successfully created.' }

Rails 3.1 - How to redirect properly with custom routes

I have a Pages model with field 'customURL'. I can do page#show at '/:customurl'. but because i've defined page show that way in routes, my create action now does a redirect on success to the wrong route. What should I change to most cleanly fix the redirect properly to point to '/:customurl' on save?
controller:
def create
#page = Page.new(params[:page])
respond_to do |format|
if #page.save
format.html { redirect_to page_url, notice: 'Page was successfully created.' }
format.json { render json: #page, status: :created, location: #page }
else
format.html { render action: "new" }
format.json { render json: #page.errors, status: :unprocessable_entity }
end
end
end
routes:
resources :pages
...
get "/:customURL" => "pages#show"
Thanks!
In routes.rb, you can add magic helpers.
get "/:customURL" => "pages#show", :as => :custom
Then in your controller
format.html { redirect_to custom_url(#page. customURL), notice: ... }
Now, "/:customURL" will need to be last in your routes.rb, routes are greedy, the first to match will get it. So if you have something like "/bob" and you have a controller listening at "/bob", the controller will get it before the pages controller.

Resources