docs/parameters.md
# Parameters
Clowne provides parameters for make your cloning logic more flexible. You can see their using in [`include_association`](include_association.md#scope) and [`finalize`](finalize.md) documentation pages.
Example:
```ruby
class UserCloner < Clowne::Cloner
include_association :posts, ->(params) { where(state: params[:state]) }
finalize do |_source, record, **params|
record.email = params[:email]
end
end
operation = UserCloner.call(user, state: :draft, email: "cloned@example.com")
cloned = operation.to_record
cloned.email
# => 'cloned@example.com'
```
## Potential Problems
Clowne is born as a part of our big project and we use it for cloning really deep object relations. When we started to use params and forwarding them between parent-child cloners we got a nasty bugs.
As result we strongly recommend to use ruby keyword arguments instead of params hash:
```ruby
# Bad
finalize do |_source, record, **params|
record.email = params[:email]
end
# Good
finalize do |_source, record, email:, **|
record.email = email
end
```
## Nested Parameters
Also we implemented control over the parameters for cloning associations (you can read more [here](https://github.com/clowne-rb/clowne/issues/15)).
Let's explain what the difference:
```ruby
class UserCloner < Clowne::Cloner
# Don't pass parameters to associations
trait :default do
include_association :profile
# equal to include_association :profile, params: false
end
# Pass all parameters to associations
trait :all_params do
include_association :profile, params: true
end
# Filter parameters by key.
# Notice: value by key must be a Hash.
trait :by_key do
include_association :profile, params: :profile
end
# Execute custom block with params as argument
trait :by_block do
include_association :profile, params: Proc.new do |params|
params[:profile].map { |k, v| [k, v.upcase] }.to_h
end
end
# Execute custom block with params and parent record as arguments
trait :by_block_with_parent do
include_association :profile, params: Proc.new do |params, user|
{
name: params[:profile][:name],
email: user.email
}
end
end
end
class ProfileCloner < Clowne::Cloner
finalize do |_source, record, **params|
record.jsonb_field = params
end
end
# Execute:
def get_profile_jsonb(user, trait)
params = {profile: {name: "John", surname: "Cena"}}
cloned = UserCloner.call(user, traits: trait, **params).to_record
cloned.profile.jsonb_field
end
get_profile_jsonb(user, :default)
# => {}
get_profile_jsonb(user, :all_params)
# => { profile: { name: 'John', surname: 'Cena' } }
get_profile_jsonb(user, :by_key)
# => { name: 'John', surname: 'Cena' }
get_profile_jsonb(user, :by_block)
# => { name: 'JOHN', surname: 'CENA' }
get_profile_jsonb(user, :by_block_with_parent)
# => { name: 'JOHN', email: user.email }
```