16

私は最近プロジェクトで ActiveAdmin を使い始めました。ほとんどすべてがうまく機能しますが、それを Friendly_id gem と組み合わせて使用​​すると問題が発生します。ID が readonly である Friendly_id 属性が原因で、フォームに ActiveRecord::ReadOnlyRecord がスローされます [私は信じています]。

{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"Rc5PmUYZt3BiLvfPQr8iCPPXlbfgjoe/n+NhCwXazNs=",
"space"=>{"name"=>"The Kosmonaut",
"address"=>"8 Sichovykh Striltsiv 24",
"email"=>"info@somedomain.com"},
"commit"=>"Update Space",
"id"=>"the-kosmonaut"}  <--- culprit

読み取り専用属性であるため、最後の行が原因であると推測しています。これは私のフォームではなく、PATH にあります。

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

ID を更新しようとして、これを修正するにはどうすればよいですか?

ActiveAdmin のフォームは次のようになります。

  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

更新:これも機能しないため、Friendly_id ではありませんか?

@watsonの提案を使用してみましたが、うまくいくはずでしたが、それでも同じエラーが発生しました;-(

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

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

コンソールで record.readonly を使用してレコードを確認すると? それはfalseを返します

更新更新: scope_to を削除すると、問題が修正されます。

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

唯一の問題は、ユーザーが所有していないレコードを表示できないようにするために scope_to が必要なことです。私の推測では (scope_to は通常 has_many で動作すると仮定しているため)、私の HABTM 関連付けは何らかの奇妙さを引き起こしているのでしょうか? つまり、ユーザー <-- HABTM --> スペース?

4

5 に答える 5

29

フロント エンドにフレンドリ ID のみが必要で、Active Admin 内では気にしない場合は、Active Admin コントローラーの Friendly_id gem の効果を元に戻すことができます。

Friendly_id がメソッドをオーバーライドする方法は正確にはわかりませんがto_param、通常の方法で実行している場合は、すべての Active Admin コントローラー内で再度オーバーライドすると修正されるはずです。たとえば、次のようになります。

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

さらに良いのは、ベースの Active Admin コントローラーに before フィルターを作成して、ActiveAdmin::ResourceControllerすべての Active Admin コントローラーに自動的に継承されるようにすることです。

最初にフィルターをconfig/initializers/active_admin.rbセットアップに追加します。

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

を開いてメソッドActiveAdmin::ResourceControllerを追加revert_friendly_idします。たとえば、の最後に次を追加します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

更新:最後のコード例を更新して、関連するモデルのないコントローラー (Active Admin Dashboard コントローラーなど) を処理するようにしました。

更新 2:上記のハックを Friendly_id gem と一緒に使用してみましたが、問題なく動作するようです :)

更新 3:フィルターをベース コントローラーに追加する前に Active Admin を追加する標準的な方法を使用するようにコードをクリーンアップしました。

于 2011-10-07T08:50:48.667 に答える
16

http://activeadmin.info/docs/2-resource-customization.html#customizing_resource_retrievalに従って、リソースの取得をカスタマイズできます。find_resourceの代わりに メソッドを使用することに注意してくださいresource。そうしないと、新しいレコードを作成できなくなります。

(詳細については、 https://github.com/gregbell/active_admin/blob/master/lib/active_admin/resource_controller/data_access.rbを確認してください)

ActiveAdmin リソース クラスに次のように記述します。

controller do
  def find_resource
    scoped_collection.where(slug: params[:id]).first!
  end
end

イニシャライザで ResourceController を変更することにより、すべてのリソースの動作を上書きすることもできactive_admin.rbます。

ActiveAdmin::ResourceController.class_eval do
  def find_resource
    if scoped_collection.is_a? FriendlyId
      scoped_collection.where(slug: params[:id]).first! 
    else
      scoped_collection.where(id: params[:id]).first!
    end
  end
end

それが役立つことを願っています!

補足: 管理インターフェースから新しいレコードを作成するときは、フォームにスラッグ フィールドを含めないでください。そうしないと、FriendlyId がスラッグを生成しません。(これはバージョン 5 以降専用だと思います)

于 2013-08-17T14:02:56.633 に答える
4

この方法は私にとってはうまくいきます。このコードを app/admin/model_name.rb に追加します

ActiveAdmin.register model_name do
  controller do
    defaults finder: :find_by_slug
  end
end
于 2013-12-11T15:50:09.623 に答える
2

Denny's solutionに追加するには、より「フレンドリーな」解決策は、 friendly_id のファインダーを使用することです。

controller do
  def find_resource
    scoped_collection.friendly.find_by_friendly_id(params[:id])
  end
end

ソース

于 2014-08-27T18:58:07.183 に答える