5

I try do create a one-to-many connection in rails4. However, although I don't get an error, the nested attribute is not stored.

What am I doing wrong?

Station-Models

class Station < ActiveRecord::Base
    has_many :adresses

    accepts_nested_attributes_for :adresses
end

Adress-Model

    class Adress < ActiveRecord::Base
        belongs_to :station
    end

Station-Controller class StationsController < ApplicationController

    def new
        @station = Station.new
        @station.adresses.build
    end

    def create
        @station = Station.new(station_params)
        @station.save
        redirect_to @station
    end

    def index
        @stations = Station.all
    end

private

    def station_params
        params.require(:station).permit(:name, adresses_attributes: [ :url ])
    end

end

Station: new.html.erb

<%= form_for :station, url: stations_path do |station| %>
    <p>
        <%= station.label :name %><br />
        <%= station.text_field :name %>
    </p>
    <%= station.fields_for :adresses do |adress| %>
        <div class="field">
            <p>
                <%= adress.label :url %><br />
                <%= adress.text_field :url %>
            </p>
        </div>
    <% end %>
    <p>
        <%= station.submit %>
    </p>
<% end %>

[edit]
I constructed a minimal example of this problem and documented it as a step-by-step instruction here: https://groups.google.com/forum/#!topic/rubyonrails-talk/4RF_CFChua0

speendo
  • 13,045
  • 22
  • 71
  • 107
  • if you also need the migration, don't hesitate to tell me ;) – speendo Jul 09 '13 at 21:13
  • Are you aware you spelled the word "addresses" in an unusual way (only one d)? As long as you're consistent, it's fine, but perhaps you misspelled something elsewhere in your code? – CodeBiker Jul 09 '13 at 23:18
  • What are the params in the adress ? Do you pemit them in address controller, maybe the problem comes from some unpermitted attributes... You can see in the log the unpermitted attributes (not really easy to find ) – phron Jul 10 '13 at 07:22
  • @CodeBiker oh, that's embarrassing... I will have find a way to correct that in my project. Thank you! However, I am consistent with this mistake. – speendo Jul 10 '13 at 07:52
  • @phron I don't have an address-controller yet. Thought I don't need one as adresses are only accessed through station. Is this maybe the cause for my problems? – speendo Jul 10 '13 at 07:57
  • @CodeBiker I'll keep the misspelled notation to create a monument of my ignorance (but mainly to keep the answers consistent). – speendo Jul 10 '13 at 08:01
  • If no addresses controller the culprit cannot be find in it ^_^. What happens when you try in console to create a station and its addresses ? the log could help you to see what happens... – phron Jul 10 '13 at 08:12
  • @phron I will try that when I'm back home. However, looking at my seed file (https://github.com/speendo/FlushFM/blob/master/db/seeds.rb) which works there doesn't seem to be an error. – speendo Jul 10 '13 at 08:18
  • 1
    another thought that come in my mind, did you try to replace "form_for :station..." by "form_for @station..." and then "station.fields_for adresses..." by "@station.fields_for adresses" (that's the way the example is provided in the Rails guide). I remember I had some problem when using a symbol(:) instead of an instance(@) – phron Jul 10 '13 at 08:47
  • @phron good idea! I will also try this when I'm back home! Thank you! Maybe I will also create a minimal example to find the exact error. – speendo Jul 10 '13 at 08:50
  • let me know the results. Have swing ! – phron Jul 10 '13 at 09:05
  • No worries, I misspell things all the time! :) If @phron's suggestion doesn't work for you, perhaps [this Railscast](http://railscasts.com/episodes/196-nested-model-form-revised?view=comments) might help? – CodeBiker Jul 10 '13 at 14:49
  • @phron concerning your second suggestion: now I get the following error: `undefined method `fields_for' for # ... <%= @station.fields_for :adresses do |adress| %>` – speendo Jul 10 '13 at 20:46
  • sorry, typo from my part should be <%= station.fields_for :adress... – phron Jul 11 '13 at 07:46
  • @phron have to try this later... btw. I constructed a minimal example and documented it in a step-by-step instruction here: https://www.ruby-forum.com/topic/4415502 – speendo Jul 12 '13 at 07:49
  • @phron or better here https://groups.google.com/forum/#!topic/rubyonrails-talk/4RF_CFChua0 – speendo Jul 12 '13 at 07:55
  • Hello, reviewing the all code you posted, I guess there's also a problem in the 'new' action in your PeopleController. It should be ```def new @person = Person.new @phones= @person.phonesb.build ``` – phron Jul 12 '13 at 09:49
  • @phron thank you. But build is only an alias for new (check out http://stackoverflow.com/questions/4954313/build-vs-new-in-rails-3 or https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb) – speendo Jul 12 '13 at 11:02
  • Doc in Active Record Association says :"When initializing a new has_one or belongs_to association you must use the build_ prefix to build the association, rather than the association.build method that would be used for has_many or has_and_belongs_to_many associations. To create one, use the create_ prefix". http://guides.rubyonrails.org/association_basics.html#detailed-association-reference – phron Jul 12 '13 at 13:12
  • ok, seems like this is good practice, thank you! Nevertheless it is just an alias for new, if I am not mistaken, right? – speendo Jul 12 '13 at 14:03
  • When you "build" an association like ```@phones = @person.phones.build``` Rails automatically sets the correct parent id in the child object. When you do ```@person.phones.new``` Rails does not know anything about the parent_id... – phron Jul 12 '13 at 14:37
  • @phron are you sure? I think this was the case for rails < 3.2.13, but now it's really the same. – speendo Jul 12 '13 at 15:07
  • maybe... I'm not a rails guru ^_^... And I think it's a good thing to follow the pactices provided in the official guides.. – phron Jul 12 '13 at 15:09
  • I perfectly agree about official practices. However, in this case https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb line 111 clearly shows that `build` is just an alias for `new`. Therefore although the code may be cleaner if I used `build` instead of `new`, it is however not the reason for the problem (I also tested that). – speendo Jul 12 '13 at 17:53
  • @phron, you were right about the @. Look here: http://stackoverflow.com/questions/17622741/params-require-permit-does-not-work-as-expected/17634183#17634183 - if you could add an answer about that, I could accept it! – speendo Jul 13 '13 at 21:01

3 Answers3

11

In Rails 4, you also need to permit the id attribute for adresses. Please do this:

def station_params
    params.require(:station).permit(:name, adresses_attributes: [ :url, :id ])
end

I'm still trying to find the official documentation for this :(

vee
  • 38,255
  • 7
  • 74
  • 78
  • `id` is only needed for updates but since you will most probably use the same method to permit the params, it won't hurt to include `id` in the list of permitted attributes for address. – jvnill Jul 10 '13 at 00:33
3

You should use form_for @station instead of form_for :station (use an instance instead of a symbol).

Cheers

phron
  • 1,795
  • 17
  • 23
0

in the StationController class, I would do :

def create
    @station = Station.new
    @station.update_attributes(station_params)
    redirect_to @station
end

instead of :

def create
    @station = Station.new(station_params)
    @station.save
    redirect_to @station
end
d34n5
  • 1,308
  • 10
  • 18