Currently [] and []= are defined as follows for ActiveRecord instances: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb def [](attr_name) read_attribute(attr_name) end def []=(attr_name, value) write_attribute(attr_name, value) end If those accessors are used then overridden attribute accessors wouldn''t be called. I didn''t find any references about the []/[]= methods in the current API, so I just mentioned them in docrails: https://github.com/lifo/docrails/commit/a49fe6ec2cb9f22a3b18d7db5ae2ee90325e9d09 But then I realized that the given example may have undesired side effects: [:deleted, :disabled].each{|p| model[p] = params[p] == ''true'' } What if "deleted=" or "disabled=" were overridden? They wouldn''t be called. So I was thinking that maybe Rails 4 could change their implementation to: def [](attr_name) send attr_name.to_s end def []=(attr_name, value) send :"#{attr_name}=", value end Better to read this style of code in some framework than inside some application... Any thoughts? Happy Easter! Rodrigo. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
They are established aliases to read and write attribute. I know changing would break a ton of my own code and various gems I author. Sent from my iPad On Apr 6, 2012, at 10:47 AM, Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com> wrote:> Currently [] and []= are defined as follows for ActiveRecord instances: > > https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb > > def [](attr_name) > read_attribute(attr_name) > end > > def []=(attr_name, value) > write_attribute(attr_name, value) > end > > If those accessors are used then overridden attribute accessors wouldn''t be called. > > I didn''t find any references about the []/[]= methods in the current API, so I just mentioned them in docrails: > > https://github.com/lifo/docrails/commit/a49fe6ec2cb9f22a3b18d7db5ae2ee90325e9d09 > > But then I realized that the given example may have undesired side effects: > > [:deleted, :disabled].each{|p| model[p] = params[p] == ''true'' } > > What if "deleted=" or "disabled=" were overridden? They wouldn''t be called. > > So I was thinking that maybe Rails 4 could change their implementation to: > > def [](attr_name) > send attr_name.to_s > end > > def []=(attr_name, value) > send :"#{attr_name}=", value > end > > Better to read this style of code in some framework than inside some application... > > Any thoughts? > > Happy Easter! > > Rodrigo. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
The whole point of [] and []= is that they alias read/write attribute directly rather than calling overrides. That way you can use them is cases where you don''t want to use the override (or even within your override.) On Fri, Apr 6, 2012 at 11:24 AM, Ken Collins <ken@actionmoniker.com> wrote:> They are established aliases to read and write attribute. I know changing > would break a ton of my own code and various gems I author. > > Sent from my iPad > > On Apr 6, 2012, at 10:47 AM, Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com> > wrote: > > Currently [] and []= are defined as follows for ActiveRecord instances: > > > https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb > > def [](attr_name) > read_attribute(attr_name) > end > > def []=(attr_name, value) > write_attribute(attr_name, value) > end > > If those accessors are used then overridden attribute accessors wouldn''t > be called. > > I didn''t find any references about the []/[]= methods in the current API, > so I just mentioned them in docrails: > > > https://github.com/lifo/docrails/commit/a49fe6ec2cb9f22a3b18d7db5ae2ee90325e9d09 > > But then I realized that the given example may have undesired side effects: > > [:deleted, :disabled].each{|p| model[p] = params[p] == ''true'' } > > What if "deleted=" or "disabled=" were overridden? They wouldn''t be called. > > So I was thinking that maybe Rails 4 could change their implementation to: > > def [](attr_name) > send attr_name.to_s > end > > def []=(attr_name, value) > send :"#{attr_name}=", value > end > > Better to read this style of code in some framework than inside some > application... > > Any thoughts? > > Happy Easter! > > Rodrigo. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to > rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/rubyonrails-core?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to > rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/rubyonrails-core?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
The intention of [] and []= is so that you can override your model''s accessor. def username=(username) self[:username] = username end If we fix the []= to call the accessor as well, that will lead to circular reference, and there will be no way to set those variables. You''re also supposed to call the model accessor''s method as well, as those are actually a public interface. [] and []= is not. - Prem On Apr 6, 2012, at 11:24 AM, Ken Collins wrote:> They are established aliases to read and write attribute. I know changing would break a ton of my own code and various gems I author. > > Sent from my iPad > > On Apr 6, 2012, at 10:47 AM, Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com> wrote: > >> Currently [] and []= are defined as follows for ActiveRecord instances: >> >> https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb >> >> def [](attr_name) >> read_attribute(attr_name) >> end >> >> def []=(attr_name, value) >> write_attribute(attr_name, value) >> end >> >> If those accessors are used then overridden attribute accessors wouldn''t be called. >> >> I didn''t find any references about the []/[]= methods in the current API, so I just mentioned them in docrails: >> >> https://github.com/lifo/docrails/commit/a49fe6ec2cb9f22a3b18d7db5ae2ee90325e9d09 >> >> But then I realized that the given example may have undesired side effects: >> >> [:deleted, :disabled].each{|p| model[p] = params[p] == ''true'' } >> >> What if "deleted=" or "disabled=" were overridden? They wouldn''t be called. >> >> So I was thinking that maybe Rails 4 could change their implementation to: >> >> def [](attr_name) >> send attr_name.to_s >> end >> >> def []=(attr_name, value) >> send :"#{attr_name}=", value >> end >> >> Better to read this style of code in some framework than inside some application... >> >> Any thoughts? >> >> Happy Easter! >> >> Rodrigo. >> >> >> -- >> You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. >> To post to this group, send email to rubyonrails-core@googlegroups.com. >> To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. >> For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. > > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Okay, I see that you don''t share the same feelings I have about this. No problem. Usually I''d want my overridden method to notice any change to those values and I find annoying have to write code like this in my controller: [:deleted, :disabled].each{|p| model.send :"#{p}=", params[p] == ''true'' } There isn''t a better alternative to this currently with AR, but as I said, I''m okay with that and I won''t push this particular discussion further. The only thing I''m concerned about is your last statement: "You''re also supposed to call the model accessor''s method as well, as those are actually a public interface. [] and []= is not." How can I know what is a public interface or not? Should I revert my documentation changes in docrails? I mean, if they are not public, I shouldn''t mention them in the official documentation. I''m worried about using them in my code and then suddenly Rails deciding to not making them available in future releases. I mean, is it reliable for me to keep using such interface instead of read/write_attribute? Best, Rodrigo. Em 06-04-2012 12:29, Prem Sichanugrist escreveu:> The intention of [] and []= is so that you can override your model''s > accessor. > > def username=(username) > self[:username] = username > end > > If we fix the []= to call the accessor as well, that will lead to > circular reference, and there will be no way to set those variables. > You''re also supposed to call the model accessor''s method as well, as > those are actually a public interface. [] and []= is not. > > - Prem > > On Apr 6, 2012, at 11:24 AM, Ken Collins wrote: > >> They are established aliases to read and write attribute. I know >> changing would break a ton of my own code and various gems I author. >> >> Sent from my iPad >> >> On Apr 6, 2012, at 10:47 AM, Rodrigo Rosenfeld Rosas >> <rr.rosas@gmail.com <mailto:rr.rosas@gmail.com>> wrote: >> >>> Currently [] and []= are defined as follows for ActiveRecord instances: >>> >>> https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_methods.rb >>> >>> def [](attr_name) >>> read_attribute(attr_name) >>> end >>> >>> def []=(attr_name, value) >>> write_attribute(attr_name, value) >>> end >>> >>> If those accessors are used then overridden attribute accessors >>> wouldn''t be called. >>> >>> I didn''t find any references about the []/[]= methods in the current >>> API, so I just mentioned them in docrails: >>> >>> https://github.com/lifo/docrails/commit/a49fe6ec2cb9f22a3b18d7db5ae2ee90325e9d09 >>> >>> But then I realized that the given example may have undesired side >>> effects: >>> >>> [:deleted, :disabled].each{|p| model[p] = params[p] == ''true'' } >>> >>> What if "deleted=" or "disabled=" were overridden? They wouldn''t be >>> called. >>> >>> So I was thinking that maybe Rails 4 could change their >>> implementation to: >>> >>> def [](attr_name) >>> send attr_name.to_s >>> end >>> >>> def []=(attr_name, value) >>> send :"#{attr_name}=", value >>> end >>> >>> Better to read this style of code in some framework than inside some >>> application... >>> >>> Any thoughts? >>> >>> Happy Easter! >>> >>> Rodrigo.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
On Sat, Apr 7, 2012 at 4:09 AM, Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com> wrote:> Okay, I see that you don''t share the same feelings I have about this. No > problem. Usually I''d want my overridden method to notice any change to those > values and I find annoying have to write code like this in my controller: > > [:deleted, :disabled].each{|p| model.send :"#{p}=", params[p] == ''true'' }model.update_attributes(params.slice(:deleted, :disabled)). And let your model handle the conversion of attribute values. Robert Pankowecki -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Em 07-04-2012 05:51, Robert Pankowecki escreveu:> On Sat, Apr 7, 2012 at 4:09 AM, Rodrigo Rosenfeld Rosas > <rr.rosas@gmail.com> wrote: >> Okay, I see that you don''t share the same feelings I have about this. No >> problem. Usually I''d want my overridden method to notice any change to those >> values and I find annoying have to write code like this in my controller: >> >> [:deleted, :disabled].each{|p| model.send :"#{p}=", params[p] == ''true'' } > model.update_attributes(params.slice(:deleted, :disabled)). > > And let your model handle the conversion of attribute values.This is not equivalent. First, update_attributes will attempt to save the record, but it wasn''t time to save it yet in my action. I can''t let the model handle the conversion because I''m converting a Grails application to Rails in parts, so the views are actually implemented in Grails at this moment and the parameters are being set by JavaScript, so I can''t be sure they''ll fit the Rails default rules for casting to boolean. I need to be sure that only ''true'' should be handled as a true value for this request. I''m using a proxy for redirecting the new implementation to the Rails application. I''ve been willing to convert this application to Rails for a long time, but I never had the chance. But last week I found a critical bug in Grails and I couldn''t find any workaround to it: http://jira.grails.org/browse/GRAILS-8994 So, I decided to take this path for fixing the application. First I needed to make sure I was able to handle authentication and authorization the same way. For that I implemented an action in the Grails application that would return me the id of the logged in user. Then all I had to do was: require ''open-uri'' user_id = open(user_id_url, ''Cookie'' => "JSESSIONID=#{cookies[''JSESSIONID'']}; rememberMe=#{cookies[''rememberMe'']}").read.to_i I created a new Devise authentication strategy and this part was completed so that I could focus in the fix for the buggy Grails action. Also I had to change the Devise session routes to match those of the Grails application. And finally, since the cookies are specific to the context path, I needed my Rails application to be mounted in the same context path. So I tried the instructions in the Configuring Rails guide, but it didn''t work for me: https://github.com/rails/rails/issues/5754 And I had to make some more changes to Devise routes as well as putting all my routes inside the context path namespace. So now I''m able to convert the Grails application to Rails in small steps and that is great! :) Actually my current authentication setup is a bit different and I handle the rememberMe cookie directly. Since I use the Shiro library to decrypt the cookie and I didn''t want to implement everything in Ruby nor use JRuby on Rails as it is a slow platform for development, I implemented the authentication service using JRuby and Drb and created another strategy using the Drb client for handling the rememberMe cookie without requiring the Grails application to be alive for remembered sessions. Well, anyway I''ll try to write an elaborate article on the details of this setup for anyone else willing to take the same approach as me for converting an application to Rails. But in those cases, the Rails API doesn''t help much on dealing with such special cases where the Rails conventions are not always followed. Currently I don''t override any property, but I wouldn''t like to have to remember that I''m bypassing any overrides if I decide to do so in the future... I mean, if there is an override, there is a reason for it to exist... They shouldn''t be just bypassed. Best, Rodrigo. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
You can use the same code with a call like: model.attributes = {} where the example was update_attributes({}). That won''t attempt to save the model. And either of those calls will assign with any overridden accessors too, so you won''t be bypassing them. James Coleman On Sat, Apr 7, 2012 at 9:29 AM, Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com>wrote:> Em 07-04-2012 05:51, Robert Pankowecki escreveu: > > On Sat, Apr 7, 2012 at 4:09 AM, Rodrigo Rosenfeld Rosas<rr.rosas@gmail.com> <rr.rosas@gmail.com> wrote: > > Okay, I see that you don''t share the same feelings I have about this. No > problem. Usually I''d want my overridden method to notice any change to those > values and I find annoying have to write code like this in my controller: > > [:deleted, :disabled].each{|p| model.send :"#{p}=", params[p] == ''true'' } > > model.update_attributes(params.slice(:deleted, :disabled)). > > And let your model handle the conversion of attribute values. > > > This is not equivalent. > > First, update_attributes will attempt to save the record, but it wasn''t > time to save it yet in my action. > > I can''t let the model handle the conversion because I''m converting a > Grails application to Rails in parts, so the views are actually implemented > in Grails at this moment and the parameters are being set by JavaScript, so > I can''t be sure they''ll fit the Rails default rules for casting to boolean. > I need to be sure that only ''true'' should be handled as a true value for > this request. > > I''m using a proxy for redirecting the new implementation to the Rails > application. I''ve been willing to convert this application to Rails for a > long time, but I never had the chance. But last week I found a critical bug > in Grails and I couldn''t find any workaround to it: > > http://jira.grails.org/browse/GRAILS-8994 > > So, I decided to take this path for fixing the application. First I needed > to make sure I was able to handle authentication and authorization the same > way. > > For that I implemented an action in the Grails application that would > return me the id of the logged in user. Then all I had to do was: > > require ''open-uri'' > user_id = open(user_id_url, ''Cookie'' => > "JSESSIONID=#{cookies[''JSESSIONID'']}; > rememberMe=#{cookies[''rememberMe'']}").read.to_i > > I created a new Devise authentication strategy and this part was completed > so that I could focus in the fix for the buggy Grails action. > > Also I had to change the Devise session routes to match those of the > Grails application. > > And finally, since the cookies are specific to the context path, I needed > my Rails application to be mounted in the same context path. So I tried the > instructions in the Configuring Rails guide, but it didn''t work for me: > > https://github.com/rails/rails/issues/5754 > > And I had to make some more changes to Devise routes as well as putting > all my routes inside the context path namespace. > > So now I''m able to convert the Grails application to Rails in small steps > and that is great! :) > > Actually my current authentication setup is a bit different and I handle > the rememberMe cookie directly. Since I use the Shiro library to decrypt > the cookie and I didn''t want to implement everything in Ruby nor use JRuby > on Rails as it is a slow platform for development, I implemented the > authentication service using JRuby and Drb and created another strategy > using the Drb client for handling the rememberMe cookie without requiring > the Grails application to be alive for remembered sessions. > > Well, anyway I''ll try to write an elaborate article on the details of this > setup for anyone else willing to take the same approach as me for > converting an application to Rails. > > But in those cases, the Rails API doesn''t help much on dealing with such > special cases where the Rails conventions are not always followed. > > Currently I don''t override any property, but I wouldn''t like to have to > remember that I''m bypassing any overrides if I decide to do so in the > future... > > I mean, if there is an override, there is a reason for it to exist... They > shouldn''t be just bypassed. > > Best, > Rodrigo. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to > rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/rubyonrails-core?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Em 07-04-2012 10:35, James Coleman escreveu:> You can use the same code with a call like: > model.attributes = {} > where the example was update_attributes({}). That won''t attempt to > save the model. And either of those calls will assign with any > overridden accessors too, so you won''t be bypassing them. >Hi James, thank you for the follow ups. Actually I was already using attributes= combined with this: http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html But I wasn''t aware that it would call the overridden methods. Thanks for getting that to my attention. I''ve just taken a look at the sources to be sure: https://github.com/rails/rails/blob/ceb33f84933639d3b61aac62e5e71fd087ab65ed/activerecord/lib/active_record/attribute_assignment.rb#L33 Thanks :) Rodrigo. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.