Giter Site home page Giter Site logo

hstore_accessor's People

Contributors

aevin1387 avatar c0nspiracy avatar crismali avatar darcygarrett avatar dkniffin avatar eprothro avatar jhirn avatar koriroys avatar lordofthelake avatar matthewlehner avatar mikechau avatar mockdeep avatar onemanstartup avatar pallymore avatar pwim avatar rhec avatar sogoodday avatar spra85 avatar thegrubbsian avatar tonycoco avatar yawn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hstore_accessor's Issues

every attribute

Let's say I have an hstore that's all integers, or all booleans.

Could we do something like hstore_accessor :options, all: :boolean?

Maybe even something dynamic? If the attribute is 'true' or 'false', catch the boolean. If calling .to_i or .to_f/d evaluates to something greater than 0, catch the int or float. That might be a bit much... just thinking out loud.

Inquiry methods

What about adding inquiry methods (e.g. Car.suv?) for attributes?
I think it'd be pretty cool.

After searching for a little while I discovered that Rails' implementation for them is not that simple. For that reason, we should use query_attribute() if we want to do that in hstore_accessor as well.

What do you guys thing about it?

Bug: nil values are being typecasted

When a value is not set it shouldn't be casted as that would lead to unexpected behaviour.

For instance:

  • a integer value when nil becomes 0.
  • a string value when nil becomes "".

And so on...

Add dirty tracking to accessors

It would be nice to extend the accessors to correctly track dirty status in the same way as native fields and add _changed? _was? and _change methods

Support for rails 4.2

Hi

I tried to use gem with rails 4.2 but it doesn't work because it have different
typecasting inferface

https://github.com/devmynd/hstore_accessor/blob/89871d834cb68b6dc21aac9255a84d3258daa813/lib/hstore_accessor/type_helpers.rb#L56-L73

methods used here doesn't exist anymore.

Here is short description what exactly changed in latest release

http://metaskills.net/2015/01/06/activerecord-42s-type-casting/

Do you want to support that feature ? I could try to prepare pr but I need your opinion first

edit

I saw you already added this feature. Could you send new version to rubygems because latest one doesn't contain code for rails 4.2

https://rubygems.org/gems/hstore_accessor

Rails 5.1 style dirty tracking?

Is there a plan to update the dirty tracking to rails 5.1 style?

Ex.
saved_change_to_{attribute}?
will_save_change_to_{attribute}?

Equivalent to ActiveRecord::Store stored_attributes

In case someone comes looking for it, here is the equivalent of getting the list of attributes (keys) for a given hstore. It's briefly mentioned in the README (bottom paragraph), but wasn't initially clear for me.

# ActiveRecord::Store
class Event < Content
    store_accessor :mydata, :name, :cost, :sponsor
end

Event.stored_attributes[:mydata]
# => [:name, :cost, :sponsor]
# Hstore Accessor gem
class Event < Content
    hstore_accessor :mydata, name: :string, cost: :string, sponsor: :string
end

Event.hstore_metadata_for_mydata.keys
# => [:name, :cost, :sponsor]

For STI cases, I added a method on the parent class to get the keys and fail safely if a child class does not have any hstore attributes defined.

class Content < ActiveRecord::Base
    def self.mydata_attribute_names
        self.hstore_metadata_for_mydata.keys rescue []
    end
    delegate :mydata_attribute_names, to: :class
end

question: YAML serialization performance

This gem looks great. Thanks for creating it and making it open-source!

I'm curious about the choice of YAML for serialization. If I'm not mistaken, it's probably not as fast as JSON or perhaps other serialization formats?

Extend column_for_attribute to work with form helpers (simple_form, etc)

Any interest in adding this to the gem itself? I find myself using using the following function in my models that I pass into simple_form builders to have the fields show up as the correct type, and not just default to text after receiving nil.

    def column_for_attribute(attr)
     atr = hstore_metadata_for_properties[attr]
     if attr
       OpenStruct.new(type: atr)
     else
       super(attr)
     end
    end

ActiveRecord 3.2 doesn't have ConnectionAdapters::Column.value_to_date

The gem specifies that it works with ActiveRecord 3.2 and higher. However, the above method only seems to be available from ActiveRecord 4.0. So attributes of type date don't work. I hope I am missing something, otherwise it may be a good idea to drop 3.2 support or use the string_to_date method when ActiveRecord 3.2 is in use.

Support multiple hstore columns in same model

When you have multiple hstore columns for one model it is not possible to use hstore_accessor, because no prefix/scope can be set or did I miss something?

I use the following config in my model.

class MyModel < AR::Base

    hstore_accessor :hstore_1, my_key: :integer
    hstore_accessor :hstore_2, my_key: :integer

end

The last hstore_accessor call overwrites the first one, which seems reasonable. It would be nice if one can set a prefix which results in different query methods instead of MyModel.my_key. What about this one?

MyModel.hstore_1_my_key
MyModel.hstore_2_my_key

Multiple JSONB columns

The store_accessor will allow to have a prefix to your data, to be able to differentiate in case you have similar names, in my case I have origin & destination which both have latitude & longitude, currently they're overlapping each others, is there a way to have a prefix?

default values

it should be possible to add default value, like
hstore_accessor :settings, share_via_facebook: :boolean, default: false

NoMethodError: undefined method `options'

Hi, I'm trying to use hstore_accessor with Rails 4 and I get this error NoMethodError: undefined method options' for #MyModel:0x007f9a452ba458`. Any idea where it may come from ?

Thanks

extend the getters and setters

My problem is I have an array field has an hstore accessor and when I present it on a form the value include the empty string(rails default behaviour), for example: ["", "1", "2"]. And for obvious reasons I would like to save it without the "". So I have tried:

class Standard < ActiveRecord::Base
  # Extensions
  hstore_accessor :properties, specific_content: :array

  def specific_content=(value)
    value = value.reject!(&:blank?)
    super(value)
  end
end

First I get an undefined method `reject!' for nil:NilClass, so I was getting the impression this was called with the wrong value, but I could see when I printed the values that it was first called with ["", "1", "2"] and the with nil. So I have tried and add a value = value.reject!(&:blank?) if value and this gives a stack level too deep and I can see that the value is printed infinitely.

So my conclusion is I cant extend the setter with something I need to do before it's called, since it seems to override what hstore_accessor is doing!

I can see here: https://github.com/devmynd/hstore_accessor/blob/master/lib/hstore_accessor/macro.rb#L25 that's where the definition happens. Do you think it's possible to change it to allow me to do something like above? Or should I be doing this in another way?

Typecasting makes it impossible to use validations

In relation to: #18

Let's say I have a Car model with an hstore field called caracteristics that contains an integer called maximum_speed like this :

class Car < ActiveRecord::Base
  hstore_accessor :caracteristics, maximum_speed: :integer
  validates :maximum_speed, numericality: true, allow_nil: true
end

The problem is that it is impossible to set the value of maximum_speed to anything other than an integer to test validation :

[1] car = Car.new
[2] car.maximum_speed = "test"
=> "test"
[3] car.maximum_speed
=> 0

The value is automatically set to 0 if it is not a number. We then cannot test validations because these are run after the integer cast.

The typecast behavior is standard for an ActiveRecord model but how can we use model validations ?

Here's what I'd expect for a normal ActiveRecord field:

class Car < ActiveRecord::Base
  validates :maximum_speed, numericality: true, allow_nil: true
end

> c = Car.new
> c.maximum_speed = 'test'
=> "test"
> c.maximum_speed
=> "test"
> c.valid?
=> false
> c.errors
=> #<... @messages={:duration=>["is not a number"]}>

Regards

Add table reference to scopes

Was working on creating a scope that joins two tables and ran into an issue where the column reference was ambiguous. It would be helpful if the scope had a table reference on it. Got around the issue by qualifying the column.

Bug: Querying Arrays

When you run Klas.xx_contains([array]), and array contains more than two strings, the operation fails.

To fix, apply this change to macro.rb:80

old line:
where("string_to_array(#{query_field}, '#{Serialization::SEPARATOR}') @> string_to_array(?, '#{Serialization::SEPARATOR}')", Array[value].flatten

new line:
where("string_to_array(#{query_field}, '#{Serialization::SEPARATOR}') @> string_to_array(?, '#{Serialization::SEPARATOR}')", Array[value].flatten.join(Serialization::SEPARATOR))

Typecasting causes unexpected behavior

Typecasting of values as they are set was added with #9 . This is causing my models to behave in a manner different than a normal ActiveRecord model attributes. Particularly, when passing in a string to an hstore attribute with the :integer type, a non-numerical string gets cast to 0. I would expect the model to accept the value and then my numericality validator to report the error when calling valid?

Example:

class MyModel < ActiveRecord::Base
    hstore_accesor :data, :number => :integer

    validates :number, numericality: { only_integer: true }
end

m = MyModel.new :number => 'lkj'
m.valid? #returns true
m.number #returns 0

In my opinion, this is causing the model to make an assumption about the input it should not be. This is particularly true when passing data in from a params hash from a form.

m.update_attributes params[:my_model]

The model should not be assuming that the user who submitted the form meant to put zero instead of lkj. This forces me as a developer to put this validation logic in the controller before being passed to the model but that is not the best place for such logic.

Dirty tracking x_changed? returns true when other hstore properties are changed

I was able to recreate this bug in 0.9.0+ . This bug does not exist in 0.6.1. FYI I'm using rails 4.0.4

hstore_accessor :properties,
                first_name: :string,
                website_url: :string

user = User.find(1)
user.first_name
=> "Harry"
user.first_name_changed?
=> false # correct
user.website_url = "http://google.com" # Change another hstore property
user.first_name_changed?
=> true # should return false since website_url was changed

Time serialization

Could you explain why time is serialized as integer not as string? There is no place where timezone can be stored with time. With string serialization we can keep timezone with time/date in database.

Doesn't work with active record's uniqueness validation

class StripePaymentPlan < PaymentPlan
  hstore_accessor :metadata,
    stripe_id: { data_type: :string, store_key: 'sid' }
  validates_uniqueness_of :stripe_id
end

Trying to call save, I get something like:

NoMethodError: undefined method `limit' for nil:NilClass
activerecord-4.1.8/lib/active_record/validations/uniqueness.rb:65:in `build_relation'

It seems ActiveRecord actually attempts to look up the column rather than checking the hstore column, any good ways to handle this?

Support for date_select

date_select pass the params like
"birth_date(1i)"=>"1980", "birth_date(2i)"=>"1", "birth_date(3i)"=>"1"

in model

hstore_accessor :profile,
                  birth_date: :time,

how can i save the birth_date?

Array should be not be nil but [] and hash should be {} by default

Hey guys,

The behaviour I expected when using an array is that if it's empty to return [] and not nil. The same behaviour for hash but returning {}.

I tried to fork it and set a pull request with the following test:

context "when assigning values it" do

  let(:product) { Product.new }
  it "correctly sends an empty array to start with" do
    expect(product.tags).to eq []
  end

  it "correctly sends an empty array to start with" do
    expect(product.reviews).to eq({})
  end
end

When I tried to push a branch I got:
git push origin empty_array_instead_of_nil

error: The requested URL returned error: 403 while accessing https://github.com/devmynd/hstore_accessor.git/info/refs
fatal: HTTP request failed

Rails 5 issue with boolean type

I've got an error when using the boolean typecast within Rails 5.0.0.beta3. All other types (string, datetime) work very well.

NoMethodError: undefined method `type_cast_from_user' for #<ActiveModel::Type::Boolean:0x007fc070def5c0>
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/hstore_accessor-1.0.3/lib/hstore_accessor/active_record_4.2/type_helpers.rb:27:in `cast'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/hstore_accessor-1.0.3/lib/hstore_accessor/serialization.rb:26:in `block in <module:Serialization>'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/hstore_accessor-1.0.3/lib/hstore_accessor/serialization.rb:45:in `deserialize'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/hstore_accessor-1.0.3/lib/hstore_accessor/macro.rb:76:in `block (3 levels) in hstore_accessor'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/hstore_accessor-1.0.3/lib/hstore_accessor/macro.rb:80:in `block (3 levels) in hstore_accessor'
    from (irb):7
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/commands/console.rb:65:in `start'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/commands/console_helper.rb:9:in `start'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:78:in `console'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/command.rb:20:in `run'
    from /usr/local/var/rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/railties-5.0.0.beta3/lib/rails/commands.rb:18:in `<top (required)>'
    from bin/rails:9:in `require'
    from bin/rails:9:in `<main>'

Thanks!

Reasons for deprecation of Array type support

I was trying to nest an array as a content of the hstore value. What are the reasons for the deprecation? Is there better design decision rather that having a nested array? I find it quite useful in my use cases. Thanks for the clarification in advance!

datetime drops milliseconds from the value

First let me say that this is a great gem. I found it today and it's really nice and makes hstore use much cleaner.

I need to store DateTime values in an hstore column and defining as follows:
hstore_accessor :properties,
queued_at: :datetime,
started_at: :datetime,
finished_at: :datetime

and setting queued_at, started_at, and finished_at drops off the millisecond portion of the DateTime value. I had gotten this to work in my model with the following and was looking forward to removing this code:

properties["queued_at"] = qd_value.strftime("%Q").to_i

and reconstituting using:

Time.strptime(qd_value.to_s, '%Q').to_datetime

This preserved the millisecond value of the timestamp.

With hstore_accessor is it possible to pluck an hstore field?

Say I have a User model with an hstore field called settings that contains a boolean called notifications_enabled. That allows me to do

[34] pry(main)> User.last.notifications_enabled
=> true

But if I didn't want to load the User model into an instance is there a way to utilize hstore_accessor to pluck out just the reminders_enabled value? I can currently do something like:

[35] pry(main)> User.where(id: 1).pluck("settings->'notifications_enabled'")
=> ["true"]

But that is less than ideal because we lose the translation of the string "true" to the value true and I'd rather not hardcode the Postgres "settings->'notifications_enabled'" query.

Ideally we could do something like:

User.where(id: 1).pluck(:notifications_enabled)
=> [true]

Adding to hstore Array does not work

Hi,

In my model Order I have an hstore setup as:

hstore_accessor :refund, refunds: :array

I can set an array with no trouble:

order.refunds = [123456]
=> [123456]

But I cannot push new values to an array

order.refunds.push 44332211
=> [123456,44332211]
order.refunds
=> [123456]

Same with the << syntax

Am I missing something basic here? If the class of the column is Array, I think .push and << should work... otherwise this is not too terribly useful? I would need to save the old array to some temp variable, push to that, and then set the new array?

Anyone else see this behaviour with arrays?

SimpleForm + i18n + labels

How do I define the label in yml file?

I tried so.

....
model_name:
attribute: 'name'

also

....
model_name:
hstore_field/attribute: 'name'

But I could not, is there any way?

Only mark as changed if value has changed

hstore_accessor marks the column as changed when set, even if the value is the same. It should only be marked changed if the value is different than the current value.

> user = User.first
> user.changed?
=> false
> user.show_labels
=> true
> user.show_labels = true
> user.changed?
=> true
> user.changes
=> => {"show_labels"=>[true, true]}

@hstore_accessible_attributes

TLDR; A little more metadata please to ease the migration to HStorified data.

When writing generalised code (i.e. a model concern) it's sometimes necessary to apply some kind of check across all attributes in a model. This often requires that the hstore_accessors get some special treatment. Without knowing in advance what our hstore_accessor attributes names are this can only be inferred by searching all 900 or so methods for start_with?('hstore_metadata_for'). Not so efficient when unnecessarily re-called once for every instance. This calls for a pre-load!

Could this be collected into a class attribute reader on the model named something like hstore_accessible_attributes ? Just a flat array of attribute names would be enough. e.g.

class MyModel
  hstore_accessor :my_data,
                              dongle_time: :datetime,
                              dongle_what: :string

  hstore_accessor :separate_things,
                              spangle_quantity: :decimal,
                              spangle_how: :string
end

MyModel.hstore_accessible_attributes # --> [:my_data, :separate_things]

Possible objections I could imagine

  1. But you can get nearly the same thing by looking for DB columns of the hstore type.
    This doesn't keep out hstore columns you haven't made accessors for.
  2. But isn't this overreaching what the gem is for? It's only for generating accessors. You can get those the same way as any other accessor: by listing all setter methods.
    Yes, but in practice it is used for augmenting the flat list of persisted attributes. One of the best reasons for using this gem is it keeps this just working even with hstore columns: person.update(flat_params).

Example
At work we have a concern which uses attributes.each. We then refactored one of the models which includes that concern to migrate many of those attributes into an hstore column. attributes.each no longer does the job. attributes_hstore_flattened.each would have done the job. Perhaps a method like that would be good, perhaps it's going too far.
In any case, we could have neatly done that flattening ourselves if armed with the class instance var requested here.

So to come back to what's wrong with a list of setters? It's not the same thing as a list of persisted flattened attributes and we need a little more metadata to build that.

3 . Adding class instance vars is risky risky business
It's good enough for @columns_hash, @default_attributes, @table_name, etc.. they serve a very similar type of role.

Cheers for reading. Now here's where you point out some stupid oversight I've made.

Error when installing on windows

I just tried installing this gem on windows 8.1, and got the following error:

PS C:\> gem install hstore_accessor
ERROR:  While executing gem ... (Errno::EINVAL)
    Invalid argument - C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/hstore_accessor-
1.0.0/lib/hstore_accessor/active_record_<_4.2

Any ideas?

Edit: I'm guessing it's because of these lines

Querying Hash Type?

Is it possible/beneficial to have a macro for querying the hash type?

I'm trying to figure out how to do it now, coming up unsuccessful and wondering if this is even possible to query with postgresql.

I have a User with a hstore_accessor :fee_list, :hash type, where fee_list is a hash like:

{"pickup dry cleaning" -> 15, "walk dog" -> 20}

Is it possible to query for Users where "pickup_dry_cleaning" is a key in the fee_list? And even better if I could query on the value as well.

I'm fine dropping down to SQL directly to do this in need be, but having trouble figuring out how that would look as, so far as I can tell, you can't cast a result to a hash.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.