0

I need some help here,

I have the following association on model A::B

# Model A::B belongs_to :B 

When I try to create/insert in the database a new instance of A::B

# test.log Processing by A::BController#create as HTML Parameters: {"a_b"=>{"b_id"=>"128"}} BEGIN A::B Load (0.4ms) SELECT "a_b".* FROM "a_b" WHERE "a_b"."id" = $1 LIMIT [["id", 128], ["LIMIT", 1]] ROLLBACK 

As you can see, I'm getting rollback because Rails is searching in the wrong class (A::B instead of B), therefore it's not finding the right element in database. The error message generate in the view is B is required.

# schema.rb create_table "a_b", force: :cascade do |t| t.bigint "b_id" t.index ["b_id"], name: "index_a_b_on_b_id" end add_foreign_key "a_b", "b" 

I believe the problem is related to the name used. For some reason, Rails is considering A::B and B the same when looking for the associations.

I already try to pass the option class_name: 'B' in the association, but it still use the wrong class.

Just for clarification, the real name of the classes are:

A => edital B => cargo A::B => edital_cargo # (using namespace) 

From the Rails console:

# The association for the class Edital::Cargo Edital::Cargo.reflect_on_association(:cargo) => #<ActiveRecord::Reflection::BelongsToReflection:0x00005588f76e6f60 @name=:cargo, @scope=nil, @options={:class_name=>"Cargo"}, @active_record=Edital::Cargo (call 'Edital::Cargo.connection' to establish a connection), @klass=nil, @plural_name="cargos", @type=nil, @foreign_type=nil, @constructable=true, @association_scope_cache=#<Concurrent::Map:0x005588f76e6588 entries=0 default_proc=nil>> # Below, how Rails generate the names (@element and @human are equal for both) ActiveModel::Name.new(Cargo) => #<ActiveModel::Name:0x00007fc6285f2a80 @name="Cargo", @klass=Cargo (call 'Cargo.connection' to establish a connection), @singular="cargo", @plural="cargos", @element="cargo", @human="Cargo", @collection="cargos", @param_key="cargo", @i18n_key=:cargo, @route_key="cargos", @singular_route_key="cargo"> ActiveModel::Name.new(Edital::Cargo) => #<ActiveModel::Name:0x00007fc6285d28c0 @name="Edital::Cargo", @klass=Edital::Cargo (call 'Edital::Cargo.connection' to establish a connection), @singular="edital_cargo", @plural="edital_cargos", @element="cargo", @human="Cargo", @collection="edital/cargos", @param_key="edital_cargo", @i18n_key=:"edital/cargo", @route_key="edital_cargos", @singular_route_key="edital_cargo"> 

Someone already face this problem? I can only think in the options class_name where I could specifies the model.

2
  • This is a known side effect of Rails' autoloading combined with Ruby's constant resolution. You should be able to use the scope resolution operator inside of A to reference B instead of A::B. Commented Aug 15, 2018 at 18:50
  • 1
    @coreyward maaan, that was fast! Thank! It works! I can accept your answer if you want. Commented Aug 15, 2018 at 18:59

1 Answer 1

0

This is a known side effect of Rails' autoloading combined with Ruby's constant resolution. You should be able to use the scope resolution operator inside of A to reference B instead of A::B

Sign up to request clarification or add additional context in comments.

1 Comment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.