rodmba
rodmba

Reputation: 31

Nested objects has_one relation

I'm new on rails , im trying to do a crud with 2 objects and has_one relation, I have a Project and Album , and just a :name property for each one. But when I create a project, both names are blank. here's my code:

project.rb , album.rb

class Project < ActiveRecord::Base
 has_one :album
 accepts_nested_attributes_for :album, allow_destroy: true
end

class Album < ActiveRecord::Base
 belongs_to :project
end

ProjectsController.rb

def new
 @project = Project.new
 @album = @project.build_album
end

def create
 @project = Project.new
 @album = @project.create_album(params[:album])

  respond_to do |format|
    if @project.save
      format.html { redirect_to @project, notice: 'Project was successfully    created.' }
      format.json { render :show, status: :created, location: @project }
    else
      format.html { render :new }
      format.json { render json: @project.errors, status: :unprocessable_entity }
    end
  end
end

def project_params
  params.require(:project).permit(:name, album_attributes: [:name])
end

_form.html.erb (project)

<%= form_for(@project) do |f| %>
  <% if @project.errors.any? %>
    <div id="error_explanation">
  <h2><%= pluralize(@project.errors.count, "error") %> prohibited this project from being saved:</h2>
  <ul>
   <% @project.errors.full_messages.each do |message| %>
    <li><%= message %></li>
   <% end %>
  </ul>
    </div>
   <% end %>

   <div class="field">
    <%= f.label :name, 'Project name: ' %><br>
     <%= f.text_field :name %>
   </div>

 <%= f.fields_for :album do |a| %>
   <div class="field">
     <%= a.label :name, 'Album name' %><br />
     <%= a.text_field :name %>
   </div>
 <% end %>

<div class="actions">
<%= f.submit %>
</div>

routes.rb

  resources :projects do
   resources :albums
  end

SUBMITED BY THE FORM

    Started POST "/projects" for ::1 at 2016-01-22 18:39:16 -0200
Processing by ProjectsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"asJbsifN/NB2/LGY0xb8S0+OnsRlJMJqhVe3vUOzEyLPAMQN1VFcDiFOwSNcXu+V1wZ78obnc6uaacCzxDdW8A==", "project"=>{"name"=>"test", "album_attributes"=>{"name"=>"test"}}, "commit"=>"Create Project"}
   (0.2ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "projects" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "test"], ["created_at", "2016-01-22 20:39:16.515028"], ["updated_at", "2016-01-22 20:39:16.515028"]]
  SQL (0.1ms)  INSERT INTO "albums" ("name", "project_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "test"], ["project_id", 7], ["created_at", "2016-01-22 20:39:16.517545"], ["updated_at", "2016-01-22 20:39:16.517545"]]
   (0.6ms)  commit transaction
Redirected to http://localhost:3000/projects/7
Completed 302 Found in 7ms (ActiveRecord: 1.3ms)

my projets/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Project Name:</strong>
  <%= @project.name %>
</p>

<p>
  <strong>Album Name:</strong>
  <%= @project.album.name %>
</p>



<%= link_to 'Edit', edit_project_path(@project) %> |
<%= link_to 'Back', projects_path %>

When i create the project/new don't work, but if i create album/new the album get a name.


EDIT (Solution)

My code was inserting the right things on database, but i could not show in my projects show view. So, for work my projects_controller looked like this:

  def show
    @project = Project.find(params[:id])
    @album = Album.take
  end

  def create
    @project = Project.new(project_params)
  end 

For show the project :name on the view the project.find resolves, and i found that Album.take here and it works to show the album :name on the same view.

Obs: The take method retrieves a record without any implicit ordering. Obs2: the show view stay the same.

Upvotes: 2

Views: 69

Answers (1)

Richard Peck
Richard Peck

Reputation: 76784

In your create action, you need to do as follows:

def create
 @project = Project.new project_params
 # Don't need to create dependent objects

 respond_to do |format|
    if @project.save
      ...

You don't need to separately create album; all the other code looks like it should work. If it doesn't, you will need to post the submitted params from your form (to which I'll be able to write an update).

--

Update

To show the albums in the view, you just need to call the associative method:

#app/controllers/projects_controller.rb
def show
   @project = Project.find params[:id]
end

#app/views/projects/show.html.erb
<% @project.albums.each do |album| %>
   <%= album.title %>
<% end %>

Upvotes: 3

Related Questions