Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support attr readers for fields with names conflicting with Object and Kernel methods #18

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/graphql/client/schema/object_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def self.new(type, fields = {})

const_set(:READERS, {})
const_set(:PREDICATES, {})
const_set(:METHODS_TO_UNDEF, [])
end
end

Expand All @@ -27,6 +28,8 @@ class WithDefinition
include ObjectType

EMPTY_SET = Set.new.freeze
BASE_RUBY_METHODS = (Object.methods + Kernel.methods).uniq.filter { |m| m.to_s =~ /^[a-z_][a-z_0-9?]*$/ }
.map(&:to_s).to_set.freeze

attr_reader :klass, :defined_fields, :definition

Expand Down Expand Up @@ -58,6 +61,9 @@ def initialize(klass, defined_fields, definition, spreads)
name = ActiveSupport::Inflector.underscore(attr)
@klass::READERS[:"#{name}"] ||= attr
@klass::PREDICATES[:"#{name}?"] ||= attr

@klass::METHODS_TO_UNDEF << name if BASE_RUBY_METHODS.include?(name)
@klass::METHODS_TO_UNDEF << "#{name}?" if BASE_RUBY_METHODS.include?("#{name}?")
end
end

Expand Down Expand Up @@ -184,6 +190,12 @@ def initialize(data = {}, errors = Errors.new, definer = nil)

@definer = definer
@enforce_collocated_callers = source_definition && source_definition.client.enforce_collocated_callers

self.class::METHODS_TO_UNDEF.each do |method_name|
begin
singleton_class.undef_method(method_name)
rescue; end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried checking with single_class.method_defined?(method_name) but while it was returning true for i.e :method, it was returning false for :test. I'm not sure what else to try here to avoid the exception handling.

end
end

# Public: Returns the raw response data
Expand Down
41 changes: 41 additions & 0 deletions test/test_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -838,4 +838,45 @@ def test_spread_definition_defined_by_other_client
}
GRAPHQL
end

def test_field_names_that_match_ruby_built_in_methods
query_type = Class.new(GraphQL::Schema::Object) do
graphql_name "Query"
field :things, String, null: false
def things
"things"
end

field :method, String, null: false
def method
"method"
end

field :equal, String, null: false
def equal
"equal"
end

field :test, String, null: false
def test
"test"
end
end

schema = Class.new(GraphQL::Schema) do
query query_type
end

@client = ::GraphQL::Client.new(schema: schema, execute: schema)

Temp.const_set :Query, @client.parse("{ method things equal test }")

result = @client.query(Temp::Query)

assert_equal "method", result.data.method
assert_equal "things", result.data.things
assert_equal "equal", result.data.equal
assert_predicate result.data, :equal?
assert_equal "test", result.data.test
end
end