Dimas Cyriaco
2012-Feb-21 14:02 UTC
Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Dimas Cyriaco
2012-Feb-22 23:51 UTC
Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Esti Alvarez
2012-Feb-28 15:34 UTC
Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Valery Kvon
2012-Feb-28 16:00 UTC
Re: Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2012-Feb-28 16:05 UTC
Re: Making ActiveResource work with nested attributes and fields_for
On Tue, Feb 21, 2012 at 3:02 PM, Dimas Cyriaco <dimascyriaco-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Mark Peterson
2012-Mar-03 08:21 UTC
Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Mark Peterson
2012-Mar-03 08:40 UTC
Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Mark Peterson
2012-Mar-03 08:53 UTC
Re: Making ActiveResource work with nested attributes and fields_for
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 3 March 2012 10:12, Anushank Lal <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org 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.