mnort9
mnort9

Reputation: 1820

Simple rails association

I'm  new to RoR. I'm trying to create a basic web app where a Profile page shows a list of Items, which belongs to a specific profile.

So far I have:

rails generate scaffold Profile name:string
rails generate scaffold Item description:string
rake db:migrate

In the profile model: has_many :items In the item model: belongs_to :profile

When I try to create a new profile, I get the error:

undefined method `item' for #<Profile

Profile controller

class ProfilesController < ApplicationController
  # GET /profiles
  # GET /profiles.json
  def index
    @profiles = profile.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @profiles }
    end
  end

  # GET /profiles/1
  # GET /profiles/1.json
  def show
    @profile = profile.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @profile }
    end
  end

  # GET /profiles/new
  # GET /profiles/new.json
  def new
    @profile = profile.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @profile }
    end
  end

  # GET /profiles/1/edit
  def edit
    @profile = profile.find(params[:id])
  end

  # POST /profiles
  # POST /profiles.json
  def create
    @profile = profile.new(params[:profile])

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

  # PUT /profiles/1
  # PUT /profiles/1.json
  def update
    @profile = profile.find(params[:id])

    respond_to do |format|
      if @profile.update_attributes(params[:profile])
        format.html { redirect_to @profile, notice: 'profile was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /profiles/1
  # DELETE /profiles/1.json
  def destroy
    @profile = profile.find(params[:id])
    @profile.destroy

    respond_to do |format|
      format.html { redirect_to profiles_url }
      format.json { head :no_content }
    end
  end
end

Profile index.html.erb

<h1>Listing profiles</h1>

<table>
  <tr>
    <th>Name</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @profiles.each do |profile| %>
  <tr>
    <td><%= profile.name %></td>
    <td><%= link_to 'Show', profile %></td>
    <td><%= link_to 'Edit', edit_profile_path(profile) %></td>
    <td><%= link_to 'Destroy', profile, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New profile', new_profile_path %>

Profile _show.html.erb

<%= simple_form_for(@profile) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :name %>
  </div>

  <div class="form-inputs">
    <%= f.input :item %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

Full error trace:

activemodel (3.2.12) lib/active_model/attribute_methods.rb:407:in `method_missing'
activerecord (3.2.12) lib/active_record/attribute_methods.rb:149:in `method_missing'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1161:in `value_before_type_cast'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1149:in `value_before_type_cast'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1043:in `block in to_input_field_tag'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1043:in `fetch'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1043:in `to_input_field_tag'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:692:in `text_field'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:1284:in `text_field'
simple_form (2.1.0) lib/simple_form/inputs/string_input.rb:13:in `input'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:29:in `block in render'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:27:in `each'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:27:in `render'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:29:in `block in render'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:27:in `each'
simple_form (2.1.0) lib/simple_form/wrappers/many.rb:27:in `render'
simple_form (2.1.0) lib/simple_form/wrappers/root.rb:15:in `render'
simple_form (2.1.0) lib/simple_form/form_builder.rb:117:in `input'
app/views/profiles/_form.html.erb:9:in `block in _app_views_profiles__form_html_erb___911765346923063960_2183588380'
actionpack (3.2.12) lib/action_view/helpers/capture_helper.rb:40:in `block in capture'
actionpack (3.2.12) lib/action_view/helpers/capture_helper.rb:187:in `with_output_buffer'
actionpack (3.2.12) lib/action_view/helpers/capture_helper.rb:40:in `capture'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:607:in `fields_for'
actionpack (3.2.12) lib/action_view/helpers/form_helper.rb:378:in `form_for'
simple_form (2.1.0) lib/simple_form/action_view_extensions/form_helper.rb:29:in `block in simple_form_for'
simple_form (2.1.0) lib/simple_form/action_view_extensions/form_helper.rb:48:in `with_simple_form_field_error_proc'
simple_form (2.1.0) lib/simple_form/action_view_extensions/form_helper.rb:28:in `simple_form_for'
app/views/profiles/_form.html.erb:1:in `_app_views_profiles__form_html_erb___911765346923063960_2183588380'
actionpack (3.2.12) lib/action_view/template.rb:145:in `block in render'
activesupport (3.2.12) lib/active_support/notifications.rb:125:in `instrument'
actionpack (3.2.12) lib/action_view/template.rb:143:in `render'
actionpack (3.2.12) lib/action_view/renderer/partial_renderer.rb:265:in `render_partial'
actionpack (3.2.12) lib/action_view/renderer/partial_renderer.rb:238:in `block in render'
actionpack (3.2.12) lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `block in instrument'
activesupport (3.2.12) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `instrument'
actionpack (3.2.12) lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
actionpack (3.2.12) lib/action_view/renderer/partial_renderer.rb:237:in `render'
actionpack (3.2.12) lib/action_view/renderer/renderer.rb:41:in `render_partial'
actionpack (3.2.12) lib/action_view/helpers/rendering_helper.rb:27:in `render'
app/views/profiles/new.html.erb:3:in `_app_views_profiles_new_html_erb___3444063506780261827_2182112400'
actionpack (3.2.12) lib/action_view/template.rb:145:in `block in render'
activesupport (3.2.12) lib/active_support/notifications.rb:125:in `instrument'
actionpack (3.2.12) lib/action_view/template.rb:143:in `render'
actionpack (3.2.12) lib/action_view/renderer/template_renderer.rb:47:in `block (2 levels) in render_template'
actionpack (3.2.12) lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `block in instrument'
activesupport (3.2.12) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `instrument'
actionpack (3.2.12) lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
actionpack (3.2.12) lib/action_view/renderer/template_renderer.rb:46:in `block in render_template'
actionpack (3.2.12) lib/action_view/renderer/template_renderer.rb:54:in `render_with_layout'
actionpack (3.2.12) lib/action_view/renderer/template_renderer.rb:45:in `render_template'
actionpack (3.2.12) lib/action_view/renderer/template_renderer.rb:18:in `render'
actionpack (3.2.12) lib/action_view/renderer/renderer.rb:36:in `render_template'
actionpack (3.2.12) lib/action_view/renderer/renderer.rb:17:in `render'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:110:in `_render_template'
actionpack (3.2.12) lib/action_controller/metal/streaming.rb:225:in `_render_template'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:103:in `render_to_body'
actionpack (3.2.12) lib/action_controller/metal/renderers.rb:28:in `render_to_body'
actionpack (3.2.12) lib/action_controller/metal/compatibility.rb:50:in `render_to_body'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:88:in `render'
actionpack (3.2.12) lib/action_controller/metal/rendering.rb:16:in `render'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:40:in `block (2 levels) in render'
activesupport (3.2.12) lib/active_support/core_ext/benchmark.rb:5:in `block in ms'
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/benchmark.rb:295:in `realtime'
activesupport (3.2.12) lib/active_support/core_ext/benchmark.rb:5:in `ms'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:40:in `block in render'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:83:in `cleanup_view_runtime'
activerecord (3.2.12) lib/active_record/railties/controller_runtime.rb:24:in `cleanup_view_runtime'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:39:in `render'
actionpack (3.2.12) lib/action_controller/metal/implicit_render.rb:10:in `default_render'
actionpack (3.2.12) lib/action_controller/metal/mime_responds.rb:196:in `respond_to'
app/controllers/profiles_controller.rb:29:in `new'
actionpack (3.2.12) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (3.2.12) lib/abstract_controller/base.rb:167:in `process_action'
actionpack (3.2.12) lib/action_controller/metal/rendering.rb:10:in `process_action'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
activesupport (3.2.12) lib/active_support/callbacks.rb:414:in `_run__312850119216024862__process_action__607287929354052739__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (3.2.12) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `block in instrument'
activesupport (3.2.12) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:in `instrument'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
actionpack (3.2.12) lib/action_controller/metal/params_wrapper.rb:207:in `process_action'
activerecord (3.2.12) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (3.2.12) lib/abstract_controller/base.rb:121:in `process'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:45:in `process'
actionpack (3.2.12) lib/action_controller/metal.rb:203:in `dispatch'
actionpack (3.2.12) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
actionpack (3.2.12) lib/action_controller/metal.rb:246:in `block in action'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:in `call'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:in `dispatch'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:36:in `call'
journey (1.0.4) lib/journey/router.rb:68:in `block in call'
journey (1.0.4) lib/journey/router.rb:56:in `each'
journey (1.0.4) lib/journey/router.rb:56:in `call'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:601:in `call'
warden (1.2.1) lib/warden/manager.rb:35:in `block in call'
warden (1.2.1) lib/warden/manager.rb:34:in `catch'
warden (1.2.1) lib/warden/manager.rb:34:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.4.5) lib/rack/etag.rb:23:in `call'
rack (1.4.5) lib/rack/conditionalget.rb:25:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/head.rb:14:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.5) lib/rack/session/abstract/id.rb:210:in `context'
rack (1.4.5) lib/rack/session/abstract/id.rb:205:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/cookies.rb:341:in `call'
activerecord (3.2.12) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.12) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in `_run__1382692569756144731__call__1219384665416315194__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/reloader.rb:65:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.12) lib/rails/rack/logger.rb:32:in `call_app'
railties (3.2.12) lib/rails/rack/logger.rb:16:in `block in call'
activesupport (3.2.12) lib/active_support/tagged_logging.rb:22:in `tagged'
railties (3.2.12) lib/rails/rack/logger.rb:16:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.5) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.5) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.12) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.4.5) lib/rack/lock.rb:15:in `call'
actionpack (3.2.12) lib/action_dispatch/middleware/static.rb:62:in `call'
railties (3.2.12) lib/rails/engine.rb:479:in `call'
railties (3.2.12) lib/rails/application.rb:223:in `call'
rack (1.4.5) lib/rack/content_length.rb:14:in `call'
railties (3.2.12) lib/rails/rack/log_tailer.rb:17:in `call'
rack (1.4.5) lib/rack/handler/webrick.rb:59:in `service'
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

Upvotes: 0

Views: 75

Answers (2)

jedi
jedi

Reputation: 2200

First of all, your Profile object does not have 'item' field. Check your object's attributes by executing these commands:

rails console
Profile.connection
Profile

or visit your db/schema.rb file

You will see that there is no attribute :item in your object's hash.

You probably want to show the profile's items in your show.html.erb view. First though, you need to create an Item of the profile that it belongs to like so:

item = Item.new(description: "Test description", profile_id: 1)

Then you can do:

Profile.first.items

Second, you have an error in your controller. Object's class should be capitalized, so:

rails console
profile = profile.new(name: "Test profile")

will raise an error

undefined method `new' for nil:NilClass

Upvotes: 0

Leo Correa
Leo Correa

Reputation: 19789

In order for the has_many :items to work you will need to have a profile_id:integer in your Item model.

You can accomplish by doing the following command

rails g migration add_profile_id_to_items profile_id:integer
rake db:migrate

That should create the foreign key needed for the association.

After that you should be able to do things like this

@profile = Profile.create name: "MyProfile"
@item = @profile.items.build description: "This is my awesome item"
@item.save

There are different ways to create items for a profile but that's the most straight forward way. Then to retrieve those items you would do something like this

@profile = Profile.find(some_id)
@items = Item.where(profile_id: @profile.id).all

or

@profile = Profile.find(some_id)
@items = @profile.items

Upvotes: 1

Related Questions