undefined method `upload_path' - 'new' action in Ruby on Rails - ruby-on-rails

This should be super simple, but I can't see what I'm doing wrong.
The form in the 'new' page for uploads is getting an error.
'Uploads' belong to 'Event'
'Event' has many 'Uploads'
routes.rb is (as far as I know) correct.
I'm planning on using Refile to upload files to S3 (as per this tutorial... not sure if this is relevant at all though)
Upload.rb
class Upload < ActiveRecord::Base
belongs_to :event
attachment :upload_file
end
Event.rb
class Event < ActiveRecord::Base
has_many :uploads
end
uploads_controller.rb
class UploadsController < ApplicationController
before_action :set_event
def new
#upload = #event.uploads.create
end
private
def set_event
#event = Event.find(params[:event_id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
root 'pages#home'
resources :events do
resources :coupons
resources :uploads
member do
post :check
end
end
views/uploads/new.html.erb (example)
<%= form_for #upload do |f| %>
<%= f.text_field :name %>
<% end %>
When I navigate to the 'new' page, I get the following error:
undefined method `upload_path' for #<#:0x007fb8709229f0>
Why can't I add a new Upload associated with Event? I know I'm missing something super simple, but I can't put my finger on it.

As uploads is nested in events, you get url for your upload path as follow:
/events/1/uploads/new
In this case, you have to specify #event in your form_for method like this:
<%= form_for [#event, #upload] do |f| %>

Or simply
<%= form_for #event.upload do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end%>

Related

Rails not directing to show page after user submit

Working with nested routes and associations. I have a partial which creates a tenant, but after the creation it stays with the form rendered and the url changes to /tenants. Desired behavior is that it needs to redirect_to the show page. Routes are as follows:
Rails.application.routes.draw do
devise_for :landlords
authenticated :landlord do
root "properties#index", as: "authenticated_root"
end
resources :tenants
resources :properties do
resources :units
end
root 'static#home'
end
So far the properties and units work (and the landlord) Issue is with Tenants. Originally I had Tenants nested under units, but had issues there as well. Partial looks like this:
<%= form_for #tenant do |f| %>
<%= f.label "Tenant Name:" %>
<%= f.text_field :name %>
<%= f.label "Move-in Date:" %>
<%= f.date_field :move_in_date %>
<%= f.label "Back Rent Amount:" %>
$<%= f.text_field :back_rent %>
<%= f.button :Submit %>
<% end %>
<%= link_to "Cancel", root_path %>
Tenants Controller looks like this:
before_action :authenticate_landlord!
#before_action :set_unit, only: [:new, :create]
before_action :set_tenant, except: [:new, :create]
def new
#tenant = Tenant.new
end
def create
#tenant = Tenant.new(tenant_params)
if #tenant.save
redirect_to(#tenant)
else
render 'new'
end
end
def show
end
def edit
end
def update
if #tenant.update(tenant_params)
redirect_to unit_tenant_path(#tenant)
else
render 'edit'
end
end
def destroy
end
private
def set_property
#property = Property.find(params[:property_id])
end
def set_unit
#unit = Unit.find(params[:unit_id])
end
def set_tenant
#tenant = Tenant.find(params[:id])
end
def tenant_params
params.require(:tenant).permit(:name, :move_in_date, :is_late, :back_rent, :unit_id)
end
end
Models have associations:
class Tenant < ApplicationRecord
belongs_to :unit, inverse_of: :tenants
end
class Unit < ApplicationRecord
belongs_to :property, inverse_of: :units
has_many :tenants, inverse_of: :unit
end
Lastly the show#tenants in rake routes is:
tenant GET /tenants/:id(.:format) tenants#show
I have extensively searched for this topic, but haven't had any success. Any help is appreciated. Rails 5.1
The route you are showing near the end of your question:
tenant GET /tenants/:id(.:format) tenants#show
is not the tenants index; it is the individual tenants/show route. You can tell this because it includes :id, which means it will show you a specific tenant having that id.
Try running rake routes again. The index route should look like this:
tenants GET /tenants(.:format) tenants#index
If you want to return to the tenants index after creating or updating a Tenant record, then you need to specify that path in your TenantsController. In both the #create and #update actions, your redirect line (after if #tenant.save and if #tenant.update, respectively) should read:
redirect_to tenants_path
That will take you to the TenantsController, #index action.
In the alternative, if you want to return to the individual tenant show page, then instead change both of those redirects in the TenantsController in both the #create and #update actions to:
redirect_to tenant_path(#tenant)
That will take you to the TenantsController, #show action for the current #tenant.

Nested attributes wouldn't save in database

I have two models one Topic and Topic_Content.
With the following code
Route
resources :topics do
resources :topic_contents
end
Topic
class Topic < ActiveRecord::Base
has_one :topic_content
accepts_nested_attributes_for :topic_content
end
TopicContent
class TopicContent < ActiveRecord::Base
belongs_to :topics
end
Controller
class TopicsController < ApplicationController
def new
#topic = Topic.new
end
def create
# render text: params[:topic].inspect
#topic = Topic.new(topic_params)
#topic.save
end
private
def topic_params
params.require(:topic).permit(:title, topic_content_attributes: [:text])
end
end
View
<%= form_for #topic do |f| %>
<%= f.label 'Topic:' %>
<%= f.text_field :title %>
<%= f.fields_for :topic_contents do |tf| %>
<%= tf.label :text %>
<%= tf.text_area :text %> 
<% end %>  
<%= f.submit %>
<% end %>
The title will be saved correct in the topic table but the topic_content(text) wouldn't saved in the database, and I couldn't find the problem.
I'm not a Rails expert, but I'm certain you need to build the association in your controller.
In your new and edit actions you need to have:
def new
#topic = Topic.new
#topic_content = #topic.build_topic_content
end
Because this is a has_one/belongs_to you need to have it look that way. If it was a many association you'd build it with something like #topic_content = #topic.topic_contents.build.
I'm pretty sure it's just a matter of building the association in the right controller, which, I believe, for you, is the topic controller.
Your view should be as follow:
f.fields_for :topic_content do |content_fields|
^

Deleting a HABTM object

I have the following code which gives me an ActionView::Template::Error (undefined methodroster_path' for #<#:0x007fe34005c208>):`
While in the background it deletes the association player_roster (Has and belongs to many), but i want to delete it when i press the link.
The roster path is nested within a team, but the issue is regarding roster and players.
<%= form_for [#team, #roster] do |f| %>
<% #players.each do |player| %>
<%= player.gamertag %>
<%= link_to "Delete", player.rosters.delete(#roster) %>
<% end %>
<% end %>
:Update
Player.rb
class Player < ActiveRecord::Base
has_and_belongs_to_many :rosters
belongs_to :country
mount_uploader :picture, PictureUploader
end
Roster.rb
class Roster < ActiveRecord::Base
has_and_belongs_to_many :players
has_many :placements
belongs_to :team, touch: true
end
The way you are doing it now will call your delete when the page loads. You can't link to arbitrary Ruby code, you need to link to a route and controller action which will perform your logic.
<%= form_for [#team, #roster] do |f| %>
<% #players.each do |player| %>
<%= player.gamertag %>
<%= link_to "Delete", player_roster_path(player, #roster), method: :delete %>
<% end %>
<% end %>
This link will route to players/:id/rosters/:id with the DELETE HTTP action, which Rails will route to the destroy method.
class RostersController < ApplicationController
def destroy
#player = Player.find(params[:player_id])
#roster = Roster.find(params[:id])
#player.rosters.destroy(#roster)
# redirect/render
end
end
You also will need to setup player_roster_path as a route in config/routes.rb
resources :players do
resources :rosters, only: [:destroy] # you may have other routes here as well
end

Simple Rails form: undefined method `categories_path'

As a first-time Rails user, I have to say I'm loving the Rails way of doing things. However, I'm running into an issue trying to create a simple form. I get the following error:
undefined method `categories_path' for #<#<Class:0x007f0440365880>:0x007f0430256cd8>
I tried creating a categories_path method in the controller (though I'm not sure what it would be for), but that didn't fix the error. Any rails experts out there know what's going on?
Here's the relevant code:
views/category/new.html.erb
<%= form_for #category do |f| %>
<%= f.label :category %>
<%= f.text_field :name %><br />
<%= f.submit %>
<% end %>
routes.rb
Jackeyes::Application.routes.draw do
scope "/admin" do
resources :product, :category
end
end
category_controller.rb
class CategoryController < ApplicationController
def index
#category = Category.all
end
def new
#category = Category.new
end
def create
#category = Category.new(params[:category])
#category.save
end
end
Make your resources plural:
resources :products, :categories
And try again.

rails - update_attributes for just part of the model; file uploading

I want to add the ability of a user to have several pictures associated with his / her user account.
I have the following classes:
class User < ActiveRecord::Base
has_many :assets
accepts_nested_attributes_for :assets
end
class Asset < ActiveRecord::Base
belongs_to :assetable, :polymorphic => true
belongs_to :user
end
I want to have a screen that just has the upload image functionality:
def add_profile_picture
#user=User.find(params[:id])
1.times {#user.assets.build}
end
form:
<%= form_for #user do |u| %>
<%= u.fields_for :assets do |asset| %>
<%= asset.file_field :asset %>
<%= asset.text_field :description %><br />
<% end %>
<%=u.submit %>
<% end %>
When I submit, it looks like the id value goes in ok in development.log:
"id"=>"1"
but I get the error:
undefined method `update_attributes' for nil:NilClass
Since I just have the asset fields, is there anything special I need to do? Also, because the belongs_to :user exists, could that be causing problems?
Basically:
asset:
user_id:
assetable_type:
assetable_id:
Any help would be appreciated. Don't do much Rails forms stuff.
thx
edit #1
class UsersController < ApplicationController
def add_profile_picture
#user=User.find(params[:id])
1.times {#user.assets.build}
end
thx
Okay - there are a few problems with your code here. I would highly recommend you read both the Action Controller Overview and the Rails Routing guides to get some more information about this.
In any case, you're getting the error because the form you have there will be trying to use the users#update action in the UsersController.
You've got a couple options. One is to create the necessary routes for the custom action, or you can create a nested resource, and make a form for adding the asset.
In this case, you'd do something like this:
in routes.rb
resources :users do
resources :assets, :only => [:new, :create] # Or any other actions you might want. It's best practise to limit these.
end
Then, in the AssetsController, you can do something similar to this:
def new
#asset = Asset.new
end
def create
#asset = Asset.new(params[:asset])
#asset.user_id = params[:user_id] if params[:user_id]
#asset.save!
end
and your form will look something like this:
<%= form_for #asset do |f| %>
<%= f.file_field :asset %>
<%= f.text_field :description %><br />
<%=f.submit %>
<% end %>

Resources