Hello,

I'm trying to make ActiveResource work with nested attributes and the
fields_for tag.

I started with a typical Rails application, with two ActiveRecord models
with one to many relationship (one band has many members).

In view 'bands/new.html.erb' I have something like this:

<%= form_for @band do |f| %>
<%= f.label: name %>
<%= f.text_field: name %>

<% f.fields_for: members do |member_form| %>
<%= member_form.label: name %>
<%= member_form.text_field: name %>

<%= member_form.label: Instrument %>
<%= member_form.text_field: Instrument %>
<% end %>

<%= f.submit >
<% end %>

In the controller I get this data as follows (in the params hash):

{
band: {
name: 'band name',
members_attributes: [
{name: 'member name' instrument: 'some instrument'}
]
}
}

When I send this params to ActiveRecord's new or create it creates the band
and members. So far so good.

So I moved the ActiveRecord models into a service and replaced them with
ActiveResource models.

However when I send the request to the service ActiveResource change these
parameters in a strange way. He turns the 'members_attributes: [...]' in
something like this:

members_attributes: [
{ members_attribute: { name: 'member name' instrument: 'some
instrument' }}
]

And the ActiveRecord on the other side cannot treat this.

Does anyone have any idea how to prevent this behavior (or why it happens)?

In a second attempt I replaced the Band.create by Band.post(nil, {},
params[:band].to_json) (which makes a request directly to the service
without going through the ActiveResource::Base#load that appears to be
source of the problem), but ActiveResource does a post to '/bands/.json'
instead of '/bands.json'. I patched ActiveResource's
'custom_method_collection_url' method, so the post goes to the right url,
but i have not yet submitted a push request because I don't know if this
will be usefull for everyone.

Actually I'm more concerned with understanding why ActiveResource's default
behavior is so strange.

Anyone know what the purpose of the method
ActiveRecord::Base#find_or_create_resource_for_collection? (I know what it
does, i just don't understand why it does it). Wouldn't it be easier if
ActiveResource simply passes my parameters for the service?

If someone can help me I would be grateful.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/-3Oy90kxuDUJ.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

Search Discussions

  • Dimas Cyriaco at Feb 22, 2012 at 11:51 pm
    Realy? No one?
    Maybe here is not the place to ask such things. I'll try somewhere else.

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/gPmMdoLOANUJ.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Esti Alvarez at Feb 28, 2012 at 3:35 pm
    I'm having the same problem. Did you manage to solve it?

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Valery Kvon at Feb 28, 2012 at 4:00 pm

    On 28.02.2012, at 19:34, Esti Alvarez wrote:

    I'm having the same problem. Did you manage to solve it?
    1) http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
    2) If nothing happens, customize view code:

    "_member_fields.html.erb":
    <%= builder.label: name %>
    <%= builder.text_field: name %>

    <%= builder.label: Instrument %>
    <%= builder.text_field: Instrument %>

    "_form.html_erb":
    <% if @band.new_record? %>
    <% f.fields_for :members_attributes do |member_form| %>
    <%= render "member_fields, :builder => member_form %>
    <% end %>
    <% else %>
    <% @band.members.each.with_index do |index, member| %>
    <% f.fields_for member, "members_attributes[#{index}]" do |member_form| %>
    <%= render "member_fields, :builder => member_form %>
    <% end %>
    <% end %>
    <% end %>


    I could write something inaccurate, but like that.

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Peter Vandenabeele at Feb 28, 2012 at 4:05 pm

    On Tue, Feb 21, 2012 at 3:02 PM, Dimas Cyriaco wrote:

    Hello,

    I'm trying to make ActiveResource work with nested attributes and the
    fields_for tag.

    I started with a typical Rails application, with two ActiveRecord models
    with one to many relationship (one band has many members).

    In view 'bands/new.html.erb' I have something like this:

    <%= form_for @band do |f| %>
    <%= f.label: name %>
    <%= f.text_field: name %>

    <% f.fields_for: members do |member_form| %>
    <%= member_form.label: name %>
    <%= member_form.text_field: name %>

    <%= member_form.label: Instrument %>
    <%= member_form.text_field: Instrument %>
    <% end %>

    <%= f.submit >
    <% end %>

    In the controller I get this data as follows (in the params hash):

    {
    band: {
    name: 'band name',
    members_attributes: [
    {name: 'member name' instrument: 'some instrument'}
    ]
    }
    }

    When I send this params to ActiveRecord's new or create it creates the
    band and members. So far so good.

    So I moved the ActiveRecord models into a service and replaced them with
    ActiveResource models.

    However when I send the request to the service ActiveResource change these
    parameters in a strange way. He turns the 'members_attributes: [...]' in
    something like this:

    members_attributes: [
    { members_attribute: { name: 'member name' instrument: 'some
    instrument' }}
    ]

    And the ActiveRecord on the other side cannot treat this.

    Does anyone have any idea how to prevent this behavior (or why it happens)?

    In a second attempt I replaced the Band.create by Band.post(nil, {},
    params[:band].to_json) (which makes a request directly to the service
    without going through the ActiveResource::Base#load that appears to be
    source of the problem), but ActiveResource does a post to '/bands/.json'
    instead of '/bands.json'. I patched ActiveResource's
    'custom_method_collection_url' method, so the post goes to the right url,
    but i have not yet submitted a push request because I don't know if this
    will be usefull for everyone.

    Actually I'm more concerned with understanding why ActiveResource's
    default behavior is so strange.

    Anyone know what the purpose of the method
    ActiveRecord::Base#find_or_create_resource_for_collection? (I know what it
    does, i just don't understand why it does it). Wouldn't it be easier if
    ActiveResource simply passes my parameters for the service?

    If someone can help me I would be grateful.
    Sorry, was a bit overloaded ...

    What I did to accept XML input for such a case was:

    * put back the "has_many" objects in an array of objects without the
    _attributes attachment.

    The hash would then be:

    {
    band: {
    name: 'band name',
    members: [
    {name: 'member name' instrument: 'some instrument'}
    ]
    }
    }

    for XML that would be:

    <band>
    <name>band name</name>
    <members type="array">
    <name>
    member name
    </name>
    <instrument>
    some instrument
    </instrument>
    </members>
    </band>

    and similar for JSON.

    Then to create a band and it's member with the assignment:

    band = Band.new(params[:band])

    which needs a fix to the members= function in the Band class.

    class Band
    # members
    has_many :members, :inverse_of => :band
    accepts_nested_attributes_for :members
    include Xml::FromXmlMembers
    end

    module Xml
    module FromXmlMembers
    extend ActiveSupport::Concern
    included do
    # for xml (on band.members=)
    def members=(members)
    case members
    when Array
    super(
    members.map |member|
    case member
    when Hash
    Member.new(member)
    else
    member
    end
    end)
    else
    raise 'members MUST be an array; maybe <members type="array"> was
    forgotten'
    end
    end
    end
    end
    end


    The catch is that the function `members= ` that is created by the has_many
    relationship
    * expects an array of Member objects
    * but the hash I typically got when parsing incoming XML data
    (and you seem to have here with ActiveResource)
    is an array of attributes hashes.

    HTH (not entirely sure ...),

    Peter

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Mark Peterson at Mar 3, 2012 at 8:21 am
    Which version of ActiveResource are you using? I also encounter what you
    are encountering while using ActiveResource 3.2.1.

    In 3.0.* there was "ActiveResource::Base.include_root_in_json" which you
    could set to false. I am not positive if that's the exact stumbling point,
    but it feels like it is.


    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/5REBTFGpR7YJ.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Mark Peterson at Mar 3, 2012 at 8:40 am
    There's a difference between ActiveModel 3.0.* and ActiveModel 3.2.*

    ActiveModel 3.0.*
    ----------
    module ActiveModel
    module Serializers
    module JSON
    def as_json(options = nil)
    hash = serializable_hash(options)

    if include_root_in_json
    custom_root = options && options[:root]
    hash = { custom_root || self.class.model_name.element => hash }
    end

    hash
    end
    end
    end
    end

    ActiveModel 3.2.*
    ----------
    module ActiveModel
    module Serializers
    module JSON
    def as_json(options = nil)
    root = include_root_in_json
    root = options[:root] if options.try(:key?, :root)
    if root
    root = self.class.model_name.element if root == true
    { root => serializable_hash(options) }
    else
    serializable_hash(options)
    end
    end
    end
    end
    end


    I think this has something to do with it. Apologies if I set you on a wild
    goose chase.

    On Saturday, March 3, 2012 3:21:10 AM UTC-5, Mark Peterson wrote:

    Which version of ActiveResource are you using? I also encounter what you
    are encountering while using ActiveResource 3.2.1.

    In 3.0.* there was "ActiveResource::Base.include_root_in_json" which you
    could set to false. I am not positive if that's the exact stumbling point,
    but it feels like it is.

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/qFMlHrzBHhkJ.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Mark Peterson at Mar 3, 2012 at 8:53 am
    Put a new file in your initializers with this code below and see if it
    helps:

    module ActiveResource
    class Base
    self.include_root_in_json = false
    end
    module Formats
    module JsonFormat
    def decode(json)
    ActiveSupport::JSON.decode(json)
    end
    end
    end
    end


    module ActiveModel
    module Serializers
    module JSON
    def as_json(options = nil)
    hash = serializable_hash(options)
    if include_root_in_json
    custom_root = options && options[:root]
    hash = { custom_root || self.class.model_name.element => hash }
    end
    hash
    end

    def from_json(json)
    hash = ActiveSupport::JSON.decode(json)
    hash = hash.values.first if include_root_in_json
    self.attributes = hash
    self
    end
    end
    end
    end

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/cXrRFRCQ59EJ.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Anushank Lal at Mar 3, 2012 at 10:12 am
    I am creating application which requires User management of various
    levels for authorization of different level of users.

    I want several models:
    Admin_user
    Project Manager
    Company
    Clients
    Account : have many users of all level.Every user have account.

    See below the relations between our models:

    1. Admin_user : have many project managers and can give rights to
    project manager.It can add and delete Project managers.Admin can
    access or manage any level of this application i.e. Its a SUPER USER.

    2.Project manager : have many companies.It can create and delete many
    companies. Project Manager can also add new project manager if
    Admin_user give right to him to create new project manager.its all
    depends on Admin_user to give or take rights from PM.

    3. Companies : can create and delete many client_users but cannot
    create any company in th same level.Company also start or stop rights
    of client.

    4.Client :can have account login and use services provided by company
    nothing more than that.

    This is my model Association. But i m confused what can i make first a
    Account model or a Admin_user model.


    Thanks

    Attachments:
    http://www.ruby-forum.com/attachment/7125/New_Text_Document.txt


    --
    Posted via http://www.ruby-forum.com/.

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
  • Colin Law at Mar 3, 2012 at 10:29 am

    On 3 March 2012 10:12, Anushank Lal wrote:
    I am creating application which requires User management of various
    levels for authorization of different level of users.

    I want several models:
    Admin_user
    Project Manager
    Company
    Clients
    Account : have many users of all level.Every user have account.
    Don't have all those different models. Just have model User and use
    Roles to limit capabilities of different user types. Have a look at
    the cancan gem.

    Colin
    See below the relations between our models:

    1. Admin_user : have many project managers and can give rights to
    project manager.It can add and delete Project managers.Admin can
    access or manage any level of this application i.e. Its a SUPER USER.

    2.Project manager : have many companies.It can create and delete many
    companies. Project Manager can also add new project manager if
    Admin_user give right to him to create new project manager.its all
    depends on Admin_user to give or take rights from PM.

    3. Companies : can create and delete many client_users but  cannot
    create any company in th same level.Company also start or stop rights
    of client.

    4.Client :can have account login and use services provided by company
    nothing more than that.

    This is my model Association. But i m confused what can i make first a
    Account model or a Admin_user model.


    Thanks

    Attachments:
    http://www.ruby-forum.com/attachment/7125/New_Text_Document.txt


    --
    Posted via http://www.ruby-forum.com/.

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.


    --
    gplus.to/clanlaw

    --
    You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
    To post to this group, send email to rubyonrails-talk@googlegroups.com.
    To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouprubyonrails-talk @
categoriesrubyonrails
postedFeb 21, '12 at 2:02p
activeMar 3, '12 at 10:29a
posts10
users7
websiterubyonrails.org
irc#RubyOnRails

People

Translate

site design / logo © 2022 Grokbase