Module: ActiveModel::Datastore
- Extended by:
- ActiveSupport::Concern
- Includes:
- ExcludedIndexes, NestedAttr, PropertyValues, TrackChanges, Dirty, Model, Validations, Validations::Callbacks
- Defined in:
- lib/active_model/datastore.rb,
lib/active_model/datastore/version.rb,
lib/active_model/datastore/nested_attr.rb,
lib/active_model/datastore/track_changes.rb,
lib/active_model/datastore/property_values.rb,
lib/active_model/datastore/excluded_indexes.rb,
lib/active_model/datastore/errors.rb
Overview
Active Model Datastore
Makes the google-cloud-datastore gem compliant with active_model conventions and compatible with your Rails 5+ applications.
Let’s start by implementing the model:
class User
include ActiveModel::Datastore
attr_accessor :email, :enabled, :name, :role, :state
before_validation :set_default_values
after_validation :format_values
before_save { puts '** something can happen before save **'}
after_save { puts '** something can happen after save **'}
validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
validates :name, presence: true, length: { maximum: 30 }
validates :role, presence: true
def entity_properties
%w[email enabled name role]
end
def set_default_values
default_property_value :enabled, true
default_property_value :role, 1
end
def format_values
format_property_value :role, :integer
end
end
Using ‘attr_accessor` the attributes of the model are defined. Validations and Callbacks all work as you would expect. However, `entity_properties` is new. Data objects in Google Cloud Datastore are known as entities. Entities are of a kind. An entity has one or more named properties, each of which can have one or more values. Think of them like this:
-
‘Kind’ (which is your table)
-
‘Entity’ (which is the record from the table)
-
‘Property’ (which is the attribute of the record)
The ‘entity_properties` method defines an Array of the properties that belong to the entity in cloud datastore. With this approach, Rails deals solely with ActiveModel objects. The objects are converted to/from entities as needed during save/query operations.
We have also added the ability to set default property values and type cast the format of values for entities.
Now on to the controller! A scaffold generated controller works out of the box:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
@users = User.all
end
def show
end
def new
@user = User.new
end
def edit
end
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
format.html { redirect_to @user, notice: 'User was successfully created.' }
else
format.html { render :new }
end
end
end
def update
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to @user, notice: 'User was successfully updated.' }
else
format.html { render :edit }
end
end
end
def destroy
@user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:email, :name)
end
end
Defined Under Namespace
Modules: ClassMethods, ExcludedIndexes, NestedAttr, PropertyValues, TrackChanges Classes: EntityError, EntityNotSavedError, Error, TrackChangesError
Constant Summary collapse
- VERSION =
'0.8.0'
Instance Method Summary collapse
-
#build_entity(parent = nil) ⇒ Entity
Builds the Cloud Datastore entity with attributes from the Model object.
- #destroy ⇒ Object
- #entity_properties ⇒ Object
-
#parent? ⇒ Boolean
Used to determine if the ActiveModel object belongs to an entity group.
-
#persisted? ⇒ Boolean
Used by ActiveModel for determining polymorphic routing.
- #save(parent = nil) ⇒ Object
-
#save! ⇒ Object
For compatibility with libraries that require the bang method version (example, factory_bot).
- #update(params) ⇒ Object
Methods included from TrackChanges
#exclude_from_save?, #reload!, #remove_unmodified_children, #tracked_attributes, #values_changed?
Methods included from PropertyValues
#default_property_value, #format_property_value
Methods included from NestedAttr
#assign_nested_attributes, #mark_for_destruction, #marked_for_destruction?, #nested_attributes?, #nested_errors, #nested_model_class_names, #nested_models
Methods included from ExcludedIndexes
#exclude_from_index, #no_index_attributes
Instance Method Details
#build_entity(parent = nil) ⇒ Entity
Builds the Cloud Datastore entity with attributes from the Model object.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/active_model/datastore.rb', line 153 def build_entity(parent = nil) entity = CloudDatastore.dataset.entity self.class.name, id if parent.present? raise ArgumentError, 'Must be a Key' unless parent.is_a? Google::Cloud::Datastore::Key entity.key.parent = parent elsif parent? entity.key.parent = self.class.parent_key(parent_key_id) end entity_properties.each do |attr| entity[attr] = instance_variable_get("@#{attr}") entity.exclude_from_indexes!(attr, true) if no_index_attributes.include? attr end entity end |
#destroy ⇒ Object
190 191 192 193 194 195 196 |
# File 'lib/active_model/datastore.rb', line 190 def destroy run_callbacks :destroy do key = CloudDatastore.dataset.key self.class.name, id key.parent = self.class.parent_key(parent_key_id) if parent? self.class.retry_on_exception? { CloudDatastore.dataset.delete key } end end |
#entity_properties ⇒ Object
128 129 130 |
# File 'lib/active_model/datastore.rb', line 128 def entity_properties [] end |
#parent? ⇒ Boolean
Used to determine if the ActiveModel object belongs to an entity group.
135 136 137 |
# File 'lib/active_model/datastore.rb', line 135 def parent? parent_key_id.present? end |
#persisted? ⇒ Boolean
Used by ActiveModel for determining polymorphic routing.
142 143 144 |
# File 'lib/active_model/datastore.rb', line 142 def persisted? id.present? end |
#save(parent = nil) ⇒ Object
169 170 171 |
# File 'lib/active_model/datastore.rb', line 169 def save(parent = nil) save_entity(parent) end |
#save! ⇒ Object
For compatibility with libraries that require the bang method version (example, factory_bot).
176 177 178 |
# File 'lib/active_model/datastore.rb', line 176 def save! save_entity || raise(EntityNotSavedError, 'Failed to save the entity') end |
#update(params) ⇒ Object
180 181 182 183 184 185 186 187 188 |
# File 'lib/active_model/datastore.rb', line 180 def update(params) assign_attributes(params) return unless valid? run_callbacks :update do entity = build_entity self.class.retry_on_exception? { CloudDatastore.dataset.save entity } end end |