Персональный блог Zhoran

Об ошибке в казалось бы работоспособном геме и взаимозависимости гемов

  •  
February 02, 2010 19:516 коммент.

На днях скачал гем acts_as_taggable_on_steroids-1.2 и попытался его прикрутить к приложению.

На удивление, сразу не получилось, хотя я следовал простой инструкции по инсталляции и по применению.

Когда я сабмитил форму с новым объектом модели (помеченной acts_as_taggable) с тегами, получал ошибку ActiveRecord::RecordInvalid: "name не может быть пустым" (Name can't be blank) как будто на попытке вставить создать тег с незаполненным названием. Естественно в контроллере оно было заполнено, а пока дошло через стек ActiveRecord до сохранения куда-то подевалось.

Оказалось, что в этом виноват гем validates_captcha-0.9.3. Проблема в том, что validates_captcha дополняя своим модулем ActiveRecord::Base прописывает в attr_accessible для всех моделей свои атрибуты. И с момента когда attr_accessible становится не nil, начинаются траблы со всеми моделями приложения. Ведь до подключения гема validates_captcha mass assignment прекрасно работал, т.к. у моделей attr_accessible был равен nil.

в файле validates_captcha/rails/init.rb ActiveRecord:::Base расширяется модулем ValidatesCaptcha:

config.after_initialize do
  ::ActiveRecord::Base.send :include, ValidatesCaptcha::ModelValidation

  #...
end

а в файле validates_captcha/lib/validates_captcha/model_validation.rb устанавливается для всех моделей attr_accessible:

module ValidatesCaptcha
  module ModelValidation
    def self.included(base) #:nodoc:
      base.extend ClassMethods
      base.send :include, InstanceMethods
      base.class_eval do
        attr_accessible :captcha_challenge, :captcha_solution
        ...
    end
  end
end

можно убедиться в этом так:

подключи этот гем через development.rb

config.gem "validates_captcha", :lib => 'validates_captcha', :source => 'http://gems.github.com', :version => '0.9.3'

запусти консоль

ruby script/console

выполни код

>class Model<ActiveRecord::Base;end; Model.attr_accessible

=> #<Set: {"captcha_solution", "captcha_challenge"}>

вот это и не нормально, что для всех моделей не важно вызван для них метод validates_captcah или нет устанавливаются общие attr_accesible.

 

Mass assignment используется, например, при создании объекта модели:

Tag.create(:name => name)

которое и перестает работать в приложении, где используется validates_captcha.

поправить просто - надо доопределить модель Tag:

class Tag

  attr_accessible :name

end

 

Вероятно автор validates_captcha установил attr_accessible для всех моделей не случайно - это заставляет определять attr_accessible, иначе mass assignment перестает работать. Насколько это его решение полезно непонятно.

, , , ,
ето не баг ето фича,причем рельсовая,походу авторvalidates_captcha тут совсем не при чем, в последних версиях есть такая штука,любой атрибут значение которого нужно вводить через форму(тоесть то самое mass_assignment) нужно либо прописывать в attr_accessible, либо(что я вляется противоположным по значению) атрибуты которые не должны вводится через формы(иил другими словами значения которых не будут мелькать в хеше hash в действиях в духе Model.create(hash)) должны быть прописаны в attr_protected, как-то так,посмотри логи,там в местах где у тебя не "доходило значение к ActiveRecord" должно быть написано нечто подобное WARNING: can't mass assign this protected attributes: tag
как-то так
ой,тоесть WARNING: can't mass assign this protected attributes: name
затупил
Спасибо за камент, Илья.
Да, мне известно что attr_accessible появился, и он не проблема.

Проблема в том, что validates_captcha дополняя своим модулем ActiveRecord::Base прописывает в attr_accessible для всех моделей свои атрибуты. И с момента когда attr_accessible становится не nil, начинаются траблы со всеми моделями приложения.

в файле гем/rails/init.rb подключается модуль ValidatesCaptcha
а в файле гем/lib/validates_captcha/model_validation.rb устанавливается для всех моделей attr_accessible


module ValidatesCaptcha
module ModelValidation
def self.included(base) #:nodoc:
base.extend ClassMethods
base.send :include, InstanceMethods

base.class_eval do
attr_accessible :captcha_challenge, :captcha_solution
...
end
end
end




можешь сам проверить
подключи этот гем через development.rb
config.gem "validates_captcha", :lib => 'validates_captcha', :source => 'http://gems.github.com', :version => '0.9.3'

запусти консоль
ruby script/console

выполни код

>class Model<ActiveRecord::Base;end; Model.attr_accessible
=> #<Set: {"captcha_solution", "captcha_challenge"}>




вот это и не нормально, что для всех моделей не важно вызван для них метод validates_captcah или нет устанавливаются общие attr_accesible.

P.S.
дополню свой пост, чтобы было сразу понятней без чтения каментов
да,действительно не по феншую сделали,лучше б уже в доках написали мол руцями нужно будет дописать эти attr_accesible, 10х за пост
во-во, не по феншую ))
Зашел посмотреть, так вот вышло обновление до версии 0.9.6 и в нем эта ошибка исправлена: из модуля ValidatesCaptcha::ModelValidation убрана эта строка:

attr_accessible :captcha_challenge, :captcha_solution




Зарегистрируйтесь для добавления сообщений