Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

ruby on rails - ActiveRecord::ReadOnlyRecord when using ActiveAdmin and Friendly_id

I started using ActiveAdmin recently in a project and almost everything works great but I'm having a problem when using it in combination with the friendly_id gem. I'm getting ActiveRecord::ReadOnlyRecord thrown for my forms [i believe] because of the friendly_id attribute whose ID is readonly:

{"utf8"=>"a?“",
"_method"=>"put",
"authenticity_token"=>"Rc5PmUYZt3BiLvfPQr8iCPPXlbfgjoe/n+NhCwXazNs=",
"space"=>{"name"=>"The Kosmonaut",
"address"=>"8 Sichovykh Striltsiv 24",
"email"=>"[email protected]"},
"commit"=>"Update Space",
"id"=>"the-kosmonaut"}  <--- culprit

I'm guessing the last line is the culprit as it's a readonly attribute, it's not in my form but rather in the PATH

http://localhost:5000/manage/spaces/the-kosmonaut/edit

How can I fix this from trying to update the ID?

Form from in ActiveAdmin looks like this:

  form do |f|
    f.inputs "Details" do
      f.input :name
      f.input :address
      f.input :email
      f.input :phone
      f.input :website
    end
    f.inputs "Content" do
      f.input :description
      f.input :blurb
    end
    f.buttons
  end

UPDATE: This doesn't work either so it's not the friendly_id?

I tried using @watson's suggestion which should have worked but still got the same error ;-(

{"utf8"=>"a?“",
 "_method"=>"put",
 "authenticity_token"=>"Rc5PmUYZt3BiLvfPQr8iCPPXlbfgjoe/n+NhCwXazNs=",
 "space"=>{"name"=>"The Kosmonaut 23"},
 "commit"=>"Update Space",
 "id"=>"6933"}

http://localhost:5000/manage/spaces/6933/edit

When I check the record in the console with record.readonly? it returns false

UPDATE UPDATE: removing the scope_to fixes the problem.

scope_to :current_user, :unless => proc{ current_user.admin? }

Only problem is I need the scope_to to prevent users from seeing records they do not own. My guess is (as I'm assuming scope_to normally works with has_many) that my HABTM association causes some weirdness? Ie Users <-- HABTM --> Spaces?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you only want friendly ID's in the front end and don't care about them inside Active Admin, you can revert the effects of the friendly_id gem for your Active Admin controllers.

I don't know exactly how friendly_id overrides the to_param method, but if it's doing it the normal way, re-overriding it inside all of your Active Admin controllers should fix it, e.g.:

ActiveAdmin.register Foobar do
  before_filter do
    Foobar.class_eval do
      def to_param
        id.to_s
      end
    end
  end
end

Even better you could create a before filter in the base Active Admin controller ActiveAdmin::ResourceController so that it is automatically inherited into all your Active Admin controllers.

First add the filter to the config/initializers/active_admin.rb setup:

ActiveAdmin.setup do |config|
  # ...
  config.before_filter :revert_friendly_id
end

The open up ActiveAdmin::ResourceController and add a revert_friendly_id method, E.g. by adding the following to the end of config/initializers/active_admin.rb:

ActiveAdmin::ResourceController.class_eval do
  protected

  def revert_friendly_id
    model_name = self.class.name.match(/::(.*)Controller$/)[1].singularize

    # Will throw a NameError if the class does not exist
    Module.const_get model_name

    eval(model_name).class_eval do
      def to_param
        id.to_s
      end
    end
  rescue NameError
  end
end

Update: I just updated the last code example to handle controllers with no related model (e.g. the Active Admin Dashboard controller)

Update 2: I just tried using the above hack together with the friendly_id gem and it seems to work just fine :)

Update 3: Cleaned up the code to use the standard way of adding Active Admin before filters to the base controller


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...