2016-10-14 3 views
0

私はパラメータを使って関数を作成し、この関数を関数全体に使用しようとしていますが、いくつかの問題があります。これをどのように変換するのか分かりません異なる2つのケース関数パラメータとオブジェクトとSQLクエリとの別の使用

def html_append(attribute) 
[...].order(attribute: :asc) [...] 
[...]current_object.attribute[...] 

あなたは鉛を持っていますか? 素晴らしい一日を過ごしましょう。

ジョナサン

答えて

1

あなたがここに何ができることはシンボルとしてで属性を送信し、次のようにそれを処理されるように:これはうまく動作するはず

def html_append(attribute) 
    Post.order(attribute => :asc) 
    current_object.public_send(attribute) 
end 

example_attribute = :name 
html_append(example_attribute) 

、public_sendを持つ唯一のことは、その与えています誰でもあなたのパブリックメソッド(sendはそれらのすべてを呼び出すためのアクセス権を与える)を呼び出すために属性アクセスを送信しているので、この属性を取得している場所に注意してください。 。

0

大きな質問です!

2番目の例では、このようなことを単純に行うことができます。

def html_append(attribute) 
    current_object[attribute] 
end 

注文方法の使用はもう少し複雑です。このようなことをするのは良い考えのように思えるかもしれないので注意してください。

def unsafe_method(attribute) 
    [...].order("#{attribute} ASC") [...] 
end 

上記の例は、SQLインジェクションに対して脆弱です。理想的な世界では、このようなことをすることができます。

Model.all.order("? ASC", attribute) 

残念ながら、これはRails APIの一部ではありません。事実は、orderに入るものがデータベースに対して安全に実行できることを確認する必要があります。既にgreat answer about thisがあります。

単純なオプションの1つは、引数を検証できる安全な属性の配列を持つことです。しかし、ifステートメントが削除された場合、このメソッドはSQLインジェクションに再度オープンされるため、この使用には注意が必要です。

def safe_method(attribute) 
    safe_order_options = ["name", "email", "phone"] 
    if attribute.in? safe_order_options 
    [...].order("#{attribute} ASC") [...] 
    end 
end 

これはさらに優れたオプションです。

def safer_method(attribute) 
    safe_order_options = ["name", "email", "phone"] 
    order_index = safe_order_options.index(attribute) 
    [...].order("#{safe_order_options[order_index]} ASC") [...] 
end 

希望するものがあります。何かタイプミスがあれば申し訳ありません。私はこのコードをテストしていませんが、原則的に動作するはずです。

+0

これは、SQLインジェクションのための解決策です。他の答えを確認してください。 –

+0

これは良い解決策ですが、属性を取得する場所を注意する必要があります。 –

+0

奇妙なことに、ソートのそのフォームに対する攻撃の例がありますか? –

0

属性を使ってこれまでのことセキュリティ上の理由から列名を確認する方がよいでしょう。

def html_append(attribute) 
    return unless Post.class.column_names.include?(attribute.to_s) 
    # Above guard condition will make sure the security of below code 
    # your code do public_send(attribute) or send(). You are safe. 
end 
関連する問題