coletrain
coletrain

Reputation: 2849

Rails 3 Nested Resources: can't get form or pages to work

I am currently working on a web app for social networking site but it seems as if getting my nested resources to work correctly is impossible. If you can help me out that would be great and I would be very thankful.

Here are my routes. I would like to have the url structure like mysite.com/username/photos /(new, edit, etc). The url structure is like so but I get an error when trying to access the forms or page. Down below I have posted what I have so far.

routes.rb

   resources :users do  
   resources :photos  
   end 

photo.rb

belongs_to :users

user.rb

has_many :photos, :foreign_key => "id", :dependent => :destroy

_form.html.erb This form has an attachment using paperclip. There is a <% before statement I removed it because it would not show the entire code below on here.

 form_for(@photos,@user) :html => {:multipart => true} do |f| %>

photos_controller.rb

 def new
  @photo = Photo.new(params[:photo])
 end

Upvotes: 2

Views: 567

Answers (3)

Simon Bagreev
Simon Bagreev

Reputation: 2859

What is the error that you get and where?

A couple things: in photo.rb:

belongs_to :user

instead of users

Are you trying to create photos from users#new page? If so, try to look at accepts_nested_attributes_for usage: in user.rb

has_many :photos, :dependent => :destroy
accepts_nested_attributes_for :photo

And then, on your users#new form:

<%= form_for @user, :html => {:multipart => true} do |f| %>
  # ... user attributes ...
  <%= f.fields_for :photo do |p| %>
    <%= p.file_field :name %>
  <% end %>
<% end%>

Also, consider using carrierwave instead of paperclip for your uploads. Here is the railcast. Good luck.

Upvotes: 0

Sean Hill
Sean Hill

Reputation: 15056

You need to create a before_filter to get the user, and the form posts to create, not new. Your photo controller should look something like:

before_filter :get_user
...

def new
  @photo = @user.photos.build
end

def create
  @photo = @user.photos.build(params[:photo])
  respond_to do |format|
    if @photo.save
      format.html {redirect_to [@user, @photo], notice: "Photo saved!"}
    else
      format.html {render action: "new"}
    end
  end
end
...
private
def get_user
  @user = User.find(params[:user_id])
end

Here, the before_filter grabs the user. In nested routes, the parent resource ID will be in params[:parent_id] or in this case, params[:user_id]. Then inside the create controller, you want to build a photo from the @user.photos collection. This will automatically create the reference between the photo and the user.

Also, your form_for has the relations backwards. It should be form_for([@user, @photo]) ..., not the other way around.

Upvotes: 1

Batkins
Batkins

Reputation: 5706

Not certain that this is the problem but it appears that your form_for tag is in the wrong format. You are closing the parentheses on the form_for tag after specifying your user, and thus it is ignoring the :html part. I would try this:

<%= form_for([@photos, @user], :html => {:multipart => true}) do |f| %>

The @photos and @user must be passed in as an array.

Also, Not sure why the @photos param would be plural. Shouldn't it be [@photo, @user]? I may be wrong on that part though.

Upvotes: 1

Related Questions